@@ -133,10 +133,13 @@ struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info,
133
133
enum btrfs_subpage_type type )
134
134
{
135
135
struct btrfs_subpage * ret ;
136
+ unsigned int real_size ;
136
137
137
138
ASSERT (fs_info -> sectorsize < PAGE_SIZE );
138
139
139
- ret = kzalloc (sizeof (struct btrfs_subpage ), GFP_NOFS );
140
+ real_size = struct_size (ret , bitmaps ,
141
+ BITS_TO_LONGS (fs_info -> subpage_info -> total_nr_bits ));
142
+ ret = kzalloc (real_size , GFP_NOFS );
140
143
if (!ret )
141
144
return ERR_PTR (- ENOMEM );
142
145
@@ -319,37 +322,59 @@ void btrfs_page_end_writer_lock(const struct btrfs_fs_info *fs_info,
319
322
unlock_page (page );
320
323
}
321
324
322
- /*
323
- * Convert the [start, start + len) range into a u16 bitmap
324
- *
325
- * For example: if start == page_offset() + 16K, len = 16K, we get 0x00f0.
326
- */
327
- static u16 btrfs_subpage_calc_bitmap (const struct btrfs_fs_info * fs_info ,
328
- struct page * page , u64 start , u32 len )
325
+ static bool bitmap_test_range_all_set (unsigned long * addr , unsigned int start ,
326
+ unsigned int nbits )
329
327
{
330
- const int bit_start = offset_in_page (start ) >> fs_info -> sectorsize_bits ;
331
- const int nbits = len >> fs_info -> sectorsize_bits ;
328
+ unsigned int found_zero ;
332
329
333
- btrfs_subpage_assert (fs_info , page , start , len );
330
+ found_zero = find_next_zero_bit (addr , start + nbits , start );
331
+ if (found_zero == start + nbits )
332
+ return true;
333
+ return false;
334
+ }
334
335
335
- /*
336
- * Here nbits can be 16, thus can go beyond u16 range. We make the
337
- * first left shift to be calculate in unsigned long (at least u32),
338
- * then truncate the result to u16.
339
- */
340
- return (u16 )(((1UL << nbits ) - 1 ) << bit_start );
336
+ static bool bitmap_test_range_all_zero (unsigned long * addr , unsigned int start ,
337
+ unsigned int nbits )
338
+ {
339
+ unsigned int found_set ;
340
+
341
+ found_set = find_next_bit (addr , start + nbits , start );
342
+ if (found_set == start + nbits )
343
+ return true;
344
+ return false;
341
345
}
342
346
347
+ #define subpage_calc_start_bit (fs_info , page , name , start , len ) \
348
+ ({ \
349
+ unsigned int start_bit; \
350
+ \
351
+ btrfs_subpage_assert(fs_info, page, start, len); \
352
+ start_bit = offset_in_page(start) >> fs_info->sectorsize_bits; \
353
+ start_bit += fs_info->subpage_info->name##_offset; \
354
+ start_bit; \
355
+ })
356
+
357
+ #define subpage_test_bitmap_all_set (fs_info , subpage , name ) \
358
+ bitmap_test_range_all_set(subpage->bitmaps, \
359
+ fs_info->subpage_info->name##_offset, \
360
+ fs_info->subpage_info->bitmap_nr_bits)
361
+
362
+ #define subpage_test_bitmap_all_zero (fs_info , subpage , name ) \
363
+ bitmap_test_range_all_zero(subpage->bitmaps, \
364
+ fs_info->subpage_info->name##_offset, \
365
+ fs_info->subpage_info->bitmap_nr_bits)
366
+
343
367
void btrfs_subpage_set_uptodate (const struct btrfs_fs_info * fs_info ,
344
368
struct page * page , u64 start , u32 len )
345
369
{
346
370
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
347
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
371
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
372
+ uptodate , start , len );
348
373
unsigned long flags ;
349
374
350
375
spin_lock_irqsave (& subpage -> lock , flags );
351
- subpage -> uptodate_bitmap |= tmp ;
352
- if (subpage -> uptodate_bitmap == U16_MAX )
376
+ bitmap_set ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
377
+ if (subpage_test_bitmap_all_set ( fs_info , subpage , uptodate ) )
353
378
SetPageUptodate (page );
354
379
spin_unlock_irqrestore (& subpage -> lock , flags );
355
380
}
@@ -358,11 +383,12 @@ void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
358
383
struct page * page , u64 start , u32 len )
359
384
{
360
385
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
361
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
386
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
387
+ uptodate , start , len );
362
388
unsigned long flags ;
363
389
364
390
spin_lock_irqsave (& subpage -> lock , flags );
365
- subpage -> uptodate_bitmap &= ~ tmp ;
391
+ bitmap_clear ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
366
392
ClearPageUptodate (page );
367
393
spin_unlock_irqrestore (& subpage -> lock , flags );
368
394
}
@@ -371,11 +397,12 @@ void btrfs_subpage_set_error(const struct btrfs_fs_info *fs_info,
371
397
struct page * page , u64 start , u32 len )
372
398
{
373
399
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
374
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
400
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
401
+ error , start , len );
375
402
unsigned long flags ;
376
403
377
404
spin_lock_irqsave (& subpage -> lock , flags );
378
- subpage -> error_bitmap |= tmp ;
405
+ bitmap_set ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
379
406
SetPageError (page );
380
407
spin_unlock_irqrestore (& subpage -> lock , flags );
381
408
}
@@ -384,12 +411,13 @@ void btrfs_subpage_clear_error(const struct btrfs_fs_info *fs_info,
384
411
struct page * page , u64 start , u32 len )
385
412
{
386
413
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
387
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
414
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
415
+ error , start , len );
388
416
unsigned long flags ;
389
417
390
418
spin_lock_irqsave (& subpage -> lock , flags );
391
- subpage -> error_bitmap &= ~ tmp ;
392
- if (subpage -> error_bitmap == 0 )
419
+ bitmap_clear ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
420
+ if (subpage_test_bitmap_all_zero ( fs_info , subpage , error ) )
393
421
ClearPageError (page );
394
422
spin_unlock_irqrestore (& subpage -> lock , flags );
395
423
}
@@ -398,11 +426,12 @@ void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info,
398
426
struct page * page , u64 start , u32 len )
399
427
{
400
428
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
401
- u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
429
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
430
+ dirty , start , len );
402
431
unsigned long flags ;
403
432
404
433
spin_lock_irqsave (& subpage -> lock , flags );
405
- subpage -> dirty_bitmap |= tmp ;
434
+ bitmap_set ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
406
435
spin_unlock_irqrestore (& subpage -> lock , flags );
407
436
set_page_dirty (page );
408
437
}
@@ -421,13 +450,14 @@ bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
421
450
struct page * page , u64 start , u32 len )
422
451
{
423
452
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
424
- u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
453
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
454
+ dirty , start , len );
425
455
unsigned long flags ;
426
456
bool last = false;
427
457
428
458
spin_lock_irqsave (& subpage -> lock , flags );
429
- subpage -> dirty_bitmap &= ~ tmp ;
430
- if (subpage -> dirty_bitmap == 0 )
459
+ bitmap_clear ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
460
+ if (subpage_test_bitmap_all_zero ( fs_info , subpage , dirty ) )
431
461
last = true;
432
462
spin_unlock_irqrestore (& subpage -> lock , flags );
433
463
return last ;
@@ -447,11 +477,12 @@ void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info,
447
477
struct page * page , u64 start , u32 len )
448
478
{
449
479
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
450
- u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
480
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
481
+ writeback , start , len );
451
482
unsigned long flags ;
452
483
453
484
spin_lock_irqsave (& subpage -> lock , flags );
454
- subpage -> writeback_bitmap |= tmp ;
485
+ bitmap_set ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
455
486
set_page_writeback (page );
456
487
spin_unlock_irqrestore (& subpage -> lock , flags );
457
488
}
@@ -460,12 +491,13 @@ void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info,
460
491
struct page * page , u64 start , u32 len )
461
492
{
462
493
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
463
- u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
494
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
495
+ writeback , start , len );
464
496
unsigned long flags ;
465
497
466
498
spin_lock_irqsave (& subpage -> lock , flags );
467
- subpage -> writeback_bitmap &= ~ tmp ;
468
- if (subpage -> writeback_bitmap == 0 ) {
499
+ bitmap_clear ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
500
+ if (subpage_test_bitmap_all_zero ( fs_info , subpage , writeback ) ) {
469
501
ASSERT (PageWriteback (page ));
470
502
end_page_writeback (page );
471
503
}
@@ -476,11 +508,12 @@ void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info,
476
508
struct page * page , u64 start , u32 len )
477
509
{
478
510
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
479
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
511
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
512
+ ordered , start , len );
480
513
unsigned long flags ;
481
514
482
515
spin_lock_irqsave (& subpage -> lock , flags );
483
- subpage -> ordered_bitmap |= tmp ;
516
+ bitmap_set ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
484
517
SetPageOrdered (page );
485
518
spin_unlock_irqrestore (& subpage -> lock , flags );
486
519
}
@@ -489,12 +522,13 @@ void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info,
489
522
struct page * page , u64 start , u32 len )
490
523
{
491
524
struct btrfs_subpage * subpage = (struct btrfs_subpage * )page -> private ;
492
- const u16 tmp = btrfs_subpage_calc_bitmap (fs_info , page , start , len );
525
+ unsigned int start_bit = subpage_calc_start_bit (fs_info , page ,
526
+ ordered , start , len );
493
527
unsigned long flags ;
494
528
495
529
spin_lock_irqsave (& subpage -> lock , flags );
496
- subpage -> ordered_bitmap &= ~ tmp ;
497
- if (subpage -> ordered_bitmap == 0 )
530
+ bitmap_clear ( subpage -> bitmaps , start_bit , len >> fs_info -> sectorsize_bits ) ;
531
+ if (subpage_test_bitmap_all_zero ( fs_info , subpage , ordered ) )
498
532
ClearPageOrdered (page );
499
533
spin_unlock_irqrestore (& subpage -> lock , flags );
500
534
}
@@ -507,12 +541,14 @@ bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \
507
541
struct page *page, u64 start, u32 len) \
508
542
{ \
509
543
struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; \
510
- const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); \
544
+ unsigned int start_bit = subpage_calc_start_bit(fs_info, page, \
545
+ name, start, len); \
511
546
unsigned long flags; \
512
547
bool ret; \
513
548
\
514
549
spin_lock_irqsave(&subpage->lock, flags); \
515
- ret = ((subpage->name##_bitmap & tmp) == tmp); \
550
+ ret = bitmap_test_range_all_set(subpage->bitmaps, start_bit, \
551
+ len >> fs_info->sectorsize_bits); \
516
552
spin_unlock_irqrestore(&subpage->lock, flags); \
517
553
return ret; \
518
554
}
@@ -609,5 +645,5 @@ void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
609
645
return ;
610
646
611
647
ASSERT (PagePrivate (page ) && page -> private );
612
- ASSERT (subpage -> dirty_bitmap == 0 );
648
+ ASSERT (subpage_test_bitmap_all_zero ( fs_info , subpage , dirty ) );
613
649
}
0 commit comments