mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 01:23:56 +02:00
btrfs: raid56: move sector_ptr::uptodate into a dedicated bitmap
The uptodate boolean member can be extracted into a bitmap, which will save us some space (1 bit in a byte vs 8 bits in a byte). Furthermore we do not need to record the uptodate bitmap for bio sectors, as if bio_sectors[].paddr is valid it means there is a bio and will be uptodate. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
17d552ab9b
commit
1810350b04
|
|
@ -151,7 +151,6 @@ struct sector_ptr {
|
||||||
* If it's INVALID_PADDR then it's not set.
|
* If it's INVALID_PADDR then it's not set.
|
||||||
*/
|
*/
|
||||||
phys_addr_t paddr;
|
phys_addr_t paddr;
|
||||||
bool uptodate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rmw_rbio_work(struct work_struct *work);
|
static void rmw_rbio_work(struct work_struct *work);
|
||||||
|
|
@ -277,13 +276,13 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
|
||||||
* read from disk.
|
* read from disk.
|
||||||
*/
|
*/
|
||||||
if (i < rbio->nr_data * rbio->stripe_nsectors)
|
if (i < rbio->nr_data * rbio->stripe_nsectors)
|
||||||
ASSERT(rbio->stripe_sectors[i].uptodate);
|
ASSERT(test_bit(i, rbio->stripe_uptodate_bitmap));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy_sectors(&rbio->stripe_sectors[i], &rbio->bio_sectors[i],
|
memcpy_sectors(&rbio->stripe_sectors[i], &rbio->bio_sectors[i],
|
||||||
rbio->bioc->fs_info->sectorsize);
|
rbio->bioc->fs_info->sectorsize);
|
||||||
rbio->stripe_sectors[i].uptodate = 1;
|
set_bit(i, rbio->stripe_uptodate_bitmap);
|
||||||
}
|
}
|
||||||
set_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
|
set_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
|
||||||
}
|
}
|
||||||
|
|
@ -318,7 +317,7 @@ static __maybe_unused bool full_page_sectors_uptodate(struct btrfs_raid_bio *rbi
|
||||||
for (i = sectors_per_page * page_nr;
|
for (i = sectors_per_page * page_nr;
|
||||||
i < sectors_per_page * page_nr + sectors_per_page;
|
i < sectors_per_page * page_nr + sectors_per_page;
|
||||||
i++) {
|
i++) {
|
||||||
if (!rbio->stripe_sectors[i].uptodate)
|
if (!test_bit(i, rbio->stripe_uptodate_bitmap))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -353,17 +352,14 @@ static void steal_rbio_page(struct btrfs_raid_bio *src,
|
||||||
{
|
{
|
||||||
const u32 sectorsize = src->bioc->fs_info->sectorsize;
|
const u32 sectorsize = src->bioc->fs_info->sectorsize;
|
||||||
const u32 sectors_per_page = PAGE_SIZE / sectorsize;
|
const u32 sectors_per_page = PAGE_SIZE / sectorsize;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dest->stripe_pages[page_nr])
|
if (dest->stripe_pages[page_nr])
|
||||||
__free_page(dest->stripe_pages[page_nr]);
|
__free_page(dest->stripe_pages[page_nr]);
|
||||||
dest->stripe_pages[page_nr] = src->stripe_pages[page_nr];
|
dest->stripe_pages[page_nr] = src->stripe_pages[page_nr];
|
||||||
src->stripe_pages[page_nr] = NULL;
|
src->stripe_pages[page_nr] = NULL;
|
||||||
|
|
||||||
/* Also update the sector->uptodate bits. */
|
/* Also update the stripe_uptodate_bitmap bits. */
|
||||||
for (i = sectors_per_page * page_nr;
|
bitmap_set(dest->stripe_uptodate_bitmap, sectors_per_page * page_nr, sectors_per_page);
|
||||||
i < sectors_per_page * page_nr + sectors_per_page; i++)
|
|
||||||
dest->stripe_sectors[i].uptodate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_data_stripe_page(struct btrfs_raid_bio *rbio, int page_nr)
|
static bool is_data_stripe_page(struct btrfs_raid_bio *rbio, int page_nr)
|
||||||
|
|
@ -1031,9 +1027,10 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
|
rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
|
||||||
rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
|
rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
|
||||||
|
rbio->stripe_uptodate_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
|
||||||
|
|
||||||
if (!rbio->stripe_pages || !rbio->bio_sectors || !rbio->stripe_sectors ||
|
if (!rbio->stripe_pages || !rbio->bio_sectors || !rbio->stripe_sectors ||
|
||||||
!rbio->finish_pointers || !rbio->error_bitmap) {
|
!rbio->finish_pointers || !rbio->error_bitmap || !rbio->stripe_uptodate_bitmap) {
|
||||||
free_raid_bio_pointers(rbio);
|
free_raid_bio_pointers(rbio);
|
||||||
kfree(rbio);
|
kfree(rbio);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
@ -1331,7 +1328,8 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
|
||||||
|
|
||||||
/* Then add the parity stripe */
|
/* Then add the parity stripe */
|
||||||
sector = rbio_pstripe_sector(rbio, sectornr);
|
sector = rbio_pstripe_sector(rbio, sectornr);
|
||||||
sector->uptodate = 1;
|
set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data, sectornr),
|
||||||
|
rbio->stripe_uptodate_bitmap);
|
||||||
pointers[stripe++] = kmap_local_sector(sector);
|
pointers[stripe++] = kmap_local_sector(sector);
|
||||||
|
|
||||||
if (has_qstripe) {
|
if (has_qstripe) {
|
||||||
|
|
@ -1340,7 +1338,8 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
|
||||||
* to fill in our p/q
|
* to fill in our p/q
|
||||||
*/
|
*/
|
||||||
sector = rbio_qstripe_sector(rbio, sectornr);
|
sector = rbio_qstripe_sector(rbio, sectornr);
|
||||||
sector->uptodate = 1;
|
set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data + 1, sectornr),
|
||||||
|
rbio->stripe_uptodate_bitmap);
|
||||||
pointers[stripe++] = kmap_local_sector(sector);
|
pointers[stripe++] = kmap_local_sector(sector);
|
||||||
|
|
||||||
assert_rbio(rbio);
|
assert_rbio(rbio);
|
||||||
|
|
@ -1496,21 +1495,19 @@ static void set_rbio_range_error(struct btrfs_raid_bio *rbio, struct bio *bio)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For subpage case, we can no longer set page Up-to-date directly for
|
* Return the index inside the rbio->stripe_sectors[] array.
|
||||||
* stripe_pages[], thus we need to locate the sector.
|
*
|
||||||
|
* Return -1 if not found.
|
||||||
*/
|
*/
|
||||||
static struct sector_ptr *find_stripe_sector(struct btrfs_raid_bio *rbio,
|
static int find_stripe_sector_nr(struct btrfs_raid_bio *rbio, phys_addr_t paddr)
|
||||||
phys_addr_t paddr)
|
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < rbio->nr_sectors; i++) {
|
||||||
|
|
||||||
for (i = 0; i < rbio->nr_sectors; i++) {
|
|
||||||
struct sector_ptr *sector = &rbio->stripe_sectors[i];
|
struct sector_ptr *sector = &rbio->stripe_sectors[i];
|
||||||
|
|
||||||
if (sector->paddr == paddr)
|
if (sector->paddr == paddr)
|
||||||
return sector;
|
return i;
|
||||||
}
|
}
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1525,11 +1522,11 @@ static void set_bio_pages_uptodate(struct btrfs_raid_bio *rbio, struct bio *bio)
|
||||||
ASSERT(!bio_flagged(bio, BIO_CLONED));
|
ASSERT(!bio_flagged(bio, BIO_CLONED));
|
||||||
|
|
||||||
btrfs_bio_for_each_block_all(paddr, bio, blocksize) {
|
btrfs_bio_for_each_block_all(paddr, bio, blocksize) {
|
||||||
struct sector_ptr *sector = find_stripe_sector(rbio, paddr);
|
int sector_nr = find_stripe_sector_nr(rbio, paddr);
|
||||||
|
|
||||||
ASSERT(sector);
|
ASSERT(sector_nr >= 0);
|
||||||
if (sector)
|
if (sector_nr >= 0)
|
||||||
sector->uptodate = 1;
|
set_bit(sector_nr, rbio->stripe_uptodate_bitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1963,7 +1960,8 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
sector = rbio_stripe_sector(rbio, faila, sector_nr);
|
sector = rbio_stripe_sector(rbio, faila, sector_nr);
|
||||||
sector->uptodate = 1;
|
set_bit(rbio_stripe_sector_index(rbio, faila, sector_nr),
|
||||||
|
rbio->stripe_uptodate_bitmap);
|
||||||
}
|
}
|
||||||
if (failb >= 0) {
|
if (failb >= 0) {
|
||||||
ret = verify_one_sector(rbio, failb, sector_nr);
|
ret = verify_one_sector(rbio, failb, sector_nr);
|
||||||
|
|
@ -1971,7 +1969,8 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
sector = rbio_stripe_sector(rbio, failb, sector_nr);
|
sector = rbio_stripe_sector(rbio, failb, sector_nr);
|
||||||
sector->uptodate = 1;
|
set_bit(rbio_stripe_sector_index(rbio, failb, sector_nr),
|
||||||
|
rbio->stripe_uptodate_bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
@ -2325,7 +2324,8 @@ static bool need_read_stripe_sectors(struct btrfs_raid_bio *rbio)
|
||||||
* thus this rbio can not be cached one, as cached one must
|
* thus this rbio can not be cached one, as cached one must
|
||||||
* have all its data sectors present and uptodate.
|
* have all its data sectors present and uptodate.
|
||||||
*/
|
*/
|
||||||
if (sector->paddr == INVALID_PADDR || !sector->uptodate)
|
if (sector->paddr == INVALID_PADDR ||
|
||||||
|
!test_bit(i, rbio->stripe_uptodate_bitmap))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2551,7 +2551,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
|
||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
p_sector.paddr = page_to_phys(page);
|
p_sector.paddr = page_to_phys(page);
|
||||||
p_sector.uptodate = 1;
|
|
||||||
page = NULL;
|
page = NULL;
|
||||||
|
|
||||||
if (has_qstripe) {
|
if (has_qstripe) {
|
||||||
|
|
@ -2563,7 +2562,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
q_sector.paddr = page_to_phys(page);
|
q_sector.paddr = page_to_phys(page);
|
||||||
q_sector.uptodate = 1;
|
|
||||||
page = NULL;
|
page = NULL;
|
||||||
pointers[rbio->real_stripes - 1] = kmap_local_sector(&q_sector);
|
pointers[rbio->real_stripes - 1] = kmap_local_sector(&q_sector);
|
||||||
}
|
}
|
||||||
|
|
@ -2781,7 +2779,8 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
|
||||||
* The bio cache may have handed us an uptodate sector. If so,
|
* The bio cache may have handed us an uptodate sector. If so,
|
||||||
* use it.
|
* use it.
|
||||||
*/
|
*/
|
||||||
if (sector->uptodate)
|
if (test_bit(rbio_stripe_sector_index(rbio, stripe, sectornr),
|
||||||
|
rbio->stripe_uptodate_bitmap))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
|
ret = rbio_add_io_sector(rbio, &bio_list, sector, stripe,
|
||||||
|
|
@ -2899,8 +2898,7 @@ void raid56_parity_cache_data_folios(struct btrfs_raid_bio *rbio,
|
||||||
foffset = 0;
|
foffset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned int sector_nr = offset_in_full_stripe >> fs_info->sectorsize_bits;
|
bitmap_set(rbio->stripe_uptodate_bitmap,
|
||||||
sector_nr < (offset_in_full_stripe + BTRFS_STRIPE_LEN) >> fs_info->sectorsize_bits;
|
offset_in_full_stripe >> fs_info->sectorsize_bits,
|
||||||
sector_nr++)
|
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits);
|
||||||
rbio->stripe_sectors[sector_nr].uptodate = true;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,9 @@ struct btrfs_raid_bio {
|
||||||
*/
|
*/
|
||||||
struct sector_ptr *stripe_sectors;
|
struct sector_ptr *stripe_sectors;
|
||||||
|
|
||||||
|
/* Each set bit means the corresponding sector in stripe_sectors[] is uptodate. */
|
||||||
|
unsigned long *stripe_uptodate_bitmap;
|
||||||
|
|
||||||
/* Allocated with real_stripes-many pointers for finish_*() calls */
|
/* Allocated with real_stripes-many pointers for finish_*() calls */
|
||||||
void **finish_pointers;
|
void **finish_pointers;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user