Skip to content

Commit 91cd1b5

Browse files
adam900710kdave
authored andcommitted
btrfs: raid56: introduce a new parameter to locate a sector
Since we cannot ensure that all bios from the higher layer are backed by large folios (e.g. direct IO, encoded read/write/send), we need the ability to locate sub-block (aka, a page) inside a full stripe. So the existing @stripe_nr + @sector_nr combination is not enough to locate such page for bs > ps cases. Introduce a new parameter, @step_nr, to locate the page of a larger fs block. The naming is following the conventions used inside btrfs elsewhere, where one step is min(sectorsize, PAGE_SIZE). It's still a preparation, only touching the following aspects: - btrfs_dump_rbio() To show the new @sector_nsteps member. - btrfs_raid_bio::sector_nsteps Recording how many steps there are inside a fs block. - Enlarge btrfs_raid_bio::*_paddrs[] size To take @sector_nsteps into consideration. - index_one_bio() - index_stripe_sectors() - memcpy_from_bio_to_stripe() - cache_rbio_pages() - need_read_stripe_sectors() Those functions are iterating *_paddrs[], which needs to take sector_nsteps into consideration. - Rename rbio_stripe_sector_index() to rbio_sector_index() The "stripe" part is not that helpful. And an extra ASSERT() before returning the result. - Add a new rbio_paddr_index() helper This will take the extra @step_nr into consideration. - The comments of btrfs_raid_bio Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9042dc0 commit 91cd1b5

2 files changed

Lines changed: 80 additions & 34 deletions

File tree

fs/btrfs/raid56.c

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ static void btrfs_dump_rbio(const struct btrfs_fs_info *fs_info,
6666

6767
dump_bioc(fs_info, rbio->bioc);
6868
btrfs_crit(fs_info,
69-
"rbio flags=0x%lx nr_sectors=%u nr_data=%u real_stripes=%u stripe_nsectors=%u scrubp=%u dbitmap=0x%lx",
69+
"rbio flags=0x%lx nr_sectors=%u nr_data=%u real_stripes=%u stripe_nsectors=%u sector_nsteps=%u scrubp=%u dbitmap=0x%lx",
7070
rbio->flags, rbio->nr_sectors, rbio->nr_data,
7171
rbio->real_stripes, rbio->stripe_nsectors,
72-
rbio->scrubp, rbio->dbitmap);
72+
rbio->sector_nsteps, rbio->scrubp, rbio->dbitmap);
7373
}
7474

7575
#define ASSERT_RBIO(expr, rbio) \
@@ -229,15 +229,20 @@ int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info)
229229

230230
static void memcpy_from_bio_to_stripe(struct btrfs_raid_bio *rbio, unsigned int sector_nr)
231231
{
232-
phys_addr_t dst = rbio->stripe_paddrs[sector_nr];
233-
phys_addr_t src = rbio->bio_paddrs[sector_nr];
232+
const u32 step = min(rbio->bioc->fs_info->sectorsize, PAGE_SIZE);
234233

235-
ASSERT(dst != INVALID_PADDR);
236-
ASSERT(src != INVALID_PADDR);
234+
ASSERT(sector_nr < rbio->nr_sectors);
235+
for (int i = 0; i < rbio->sector_nsteps; i++) {
236+
unsigned int index = sector_nr * rbio->sector_nsteps + i;
237+
phys_addr_t dst = rbio->stripe_paddrs[index];
238+
phys_addr_t src = rbio->bio_paddrs[index];
237239

238-
memcpy_page(phys_to_page(dst), offset_in_page(dst),
239-
phys_to_page(src), offset_in_page(src),
240-
rbio->bioc->fs_info->sectorsize);
240+
ASSERT(dst != INVALID_PADDR);
241+
ASSERT(src != INVALID_PADDR);
242+
243+
memcpy_page(phys_to_page(dst), offset_in_page(dst),
244+
phys_to_page(src), offset_in_page(src), step);
245+
}
241246
}
242247

243248
/*
@@ -260,7 +265,7 @@ static void cache_rbio_pages(struct btrfs_raid_bio *rbio)
260265

261266
for (i = 0; i < rbio->nr_sectors; i++) {
262267
/* Some range not covered by bio (partial write), skip it */
263-
if (rbio->bio_paddrs[i] == INVALID_PADDR) {
268+
if (rbio->bio_paddrs[i * rbio->sector_nsteps] == INVALID_PADDR) {
264269
/*
265270
* Even if the sector is not covered by bio, if it is
266271
* a data sector it should still be uptodate as it is
@@ -320,11 +325,12 @@ static __maybe_unused bool full_page_sectors_uptodate(struct btrfs_raid_bio *rbi
320325
*/
321326
static void index_stripe_sectors(struct btrfs_raid_bio *rbio)
322327
{
323-
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
328+
const u32 step = min(rbio->bioc->fs_info->sectorsize, PAGE_SIZE);
324329
u32 offset;
325330
int i;
326331

327-
for (i = 0, offset = 0; i < rbio->nr_sectors; i++, offset += sectorsize) {
332+
for (i = 0, offset = 0; i < rbio->nr_sectors * rbio->sector_nsteps;
333+
i++, offset += step) {
328334
int page_index = offset >> PAGE_SHIFT;
329335

330336
ASSERT(page_index < rbio->nr_pages);
@@ -668,21 +674,41 @@ static int rbio_can_merge(struct btrfs_raid_bio *last,
668674
return 1;
669675
}
670676

671-
static unsigned int rbio_stripe_sector_index(const struct btrfs_raid_bio *rbio,
672-
unsigned int stripe_nr,
673-
unsigned int sector_nr)
677+
/* Return the sector index for @stripe_nr and @sector_nr. */
678+
static unsigned int rbio_sector_index(const struct btrfs_raid_bio *rbio,
679+
unsigned int stripe_nr,
680+
unsigned int sector_nr)
674681
{
682+
unsigned int ret;
683+
675684
ASSERT_RBIO_STRIPE(stripe_nr < rbio->real_stripes, rbio, stripe_nr);
676685
ASSERT_RBIO_SECTOR(sector_nr < rbio->stripe_nsectors, rbio, sector_nr);
677686

678-
return stripe_nr * rbio->stripe_nsectors + sector_nr;
687+
ret = stripe_nr * rbio->stripe_nsectors + sector_nr;
688+
ASSERT(ret < rbio->nr_sectors);
689+
return ret;
690+
}
691+
692+
/* Return the paddr array index for @stripe_nr, @sector_nr and @step_nr. */
693+
static unsigned int rbio_paddr_index(const struct btrfs_raid_bio *rbio,
694+
unsigned int stripe_nr,
695+
unsigned int sector_nr,
696+
unsigned int step_nr)
697+
{
698+
unsigned int ret;
699+
700+
ASSERT_RBIO_SECTOR(step_nr < rbio->sector_nsteps, rbio, step_nr);
701+
702+
ret = rbio_sector_index(rbio, stripe_nr, sector_nr) * rbio->sector_nsteps + step_nr;
703+
ASSERT(ret < rbio->nr_sectors * rbio->sector_nsteps);
704+
return ret;
679705
}
680706

681707
/* Return a paddr from rbio->stripe_sectors, not from the bio list */
682708
static phys_addr_t rbio_stripe_paddr(const struct btrfs_raid_bio *rbio,
683709
unsigned int stripe_nr, unsigned int sector_nr)
684710
{
685-
return rbio->stripe_paddrs[rbio_stripe_sector_index(rbio, stripe_nr, sector_nr)];
711+
return rbio->stripe_paddrs[rbio_paddr_index(rbio, stripe_nr, sector_nr, 0)];
686712
}
687713

688714
/* Grab a paddr inside P stripe */
@@ -985,6 +1011,8 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
9851011
const unsigned int stripe_nsectors =
9861012
BTRFS_STRIPE_LEN >> fs_info->sectorsize_bits;
9871013
const unsigned int num_sectors = stripe_nsectors * real_stripes;
1014+
const unsigned int step = min(fs_info->sectorsize, PAGE_SIZE);
1015+
const unsigned int sector_nsteps = fs_info->sectorsize / step;
9881016
struct btrfs_raid_bio *rbio;
9891017

9901018
/* PAGE_SIZE must also be aligned to sectorsize for subpage support */
@@ -1007,8 +1035,8 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
10071035
return ERR_PTR(-ENOMEM);
10081036
rbio->stripe_pages = kcalloc(num_pages, sizeof(struct page *),
10091037
GFP_NOFS);
1010-
rbio->bio_paddrs = kcalloc(num_sectors, sizeof(phys_addr_t), GFP_NOFS);
1011-
rbio->stripe_paddrs = kcalloc(num_sectors, sizeof(phys_addr_t), GFP_NOFS);
1038+
rbio->bio_paddrs = kcalloc(num_sectors * sector_nsteps, sizeof(phys_addr_t), GFP_NOFS);
1039+
rbio->stripe_paddrs = kcalloc(num_sectors * sector_nsteps, sizeof(phys_addr_t), GFP_NOFS);
10121040
rbio->finish_pointers = kcalloc(real_stripes, sizeof(void *), GFP_NOFS);
10131041
rbio->error_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
10141042
rbio->stripe_uptodate_bitmap = bitmap_zalloc(num_sectors, GFP_NOFS);
@@ -1019,7 +1047,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
10191047
kfree(rbio);
10201048
return ERR_PTR(-ENOMEM);
10211049
}
1022-
for (int i = 0; i < num_sectors; i++) {
1050+
for (int i = 0; i < num_sectors * sector_nsteps; i++) {
10231051
rbio->stripe_paddrs[i] = INVALID_PADDR;
10241052
rbio->bio_paddrs[i] = INVALID_PADDR;
10251053
}
@@ -1037,6 +1065,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
10371065
rbio->real_stripes = real_stripes;
10381066
rbio->stripe_npages = stripe_npages;
10391067
rbio->stripe_nsectors = stripe_nsectors;
1068+
rbio->sector_nsteps = sector_nsteps;
10401069
refcount_set(&rbio->refs, 1);
10411070
atomic_set(&rbio->stripes_pending, 0);
10421071

@@ -1192,18 +1221,19 @@ static int rbio_add_io_paddr(struct btrfs_raid_bio *rbio, struct bio_list *bio_l
11921221

11931222
static void index_one_bio(struct btrfs_raid_bio *rbio, struct bio *bio)
11941223
{
1195-
const u32 sectorsize = rbio->bioc->fs_info->sectorsize;
1196-
const u32 sectorsize_bits = rbio->bioc->fs_info->sectorsize_bits;
1224+
struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
1225+
const u32 step = min(fs_info->sectorsize, PAGE_SIZE);
1226+
const u32 step_bits = min(fs_info->sectorsize_bits, PAGE_SHIFT);
11971227
struct bvec_iter iter = bio->bi_iter;
11981228
phys_addr_t paddr;
11991229
u32 offset = (bio->bi_iter.bi_sector << SECTOR_SHIFT) -
12001230
rbio->bioc->full_stripe_logical;
12011231

1202-
btrfs_bio_for_each_block(paddr, bio, &iter, sectorsize) {
1203-
unsigned int index = (offset >> sectorsize_bits);
1232+
btrfs_bio_for_each_block(paddr, bio, &iter, step) {
1233+
unsigned int index = (offset >> step_bits);
12041234

12051235
rbio->bio_paddrs[index] = paddr;
1206-
offset += sectorsize;
1236+
offset += step;
12071237
}
12081238
}
12091239

@@ -1303,7 +1333,7 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
13031333
sector_paddr_in_rbio(rbio, stripe, sectornr, 0));
13041334

13051335
/* Then add the parity stripe */
1306-
set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data, sectornr),
1336+
set_bit(rbio_sector_index(rbio, rbio->nr_data, sectornr),
13071337
rbio->stripe_uptodate_bitmap);
13081338
pointers[stripe++] = kmap_local_paddr(rbio_pstripe_paddr(rbio, sectornr));
13091339

@@ -1312,7 +1342,7 @@ static void generate_pq_vertical(struct btrfs_raid_bio *rbio, int sectornr)
13121342
* RAID6, add the qstripe and call the library function
13131343
* to fill in our p/q
13141344
*/
1315-
set_bit(rbio_stripe_sector_index(rbio, rbio->nr_data + 1, sectornr),
1345+
set_bit(rbio_sector_index(rbio, rbio->nr_data + 1, sectornr),
13161346
rbio->stripe_uptodate_bitmap);
13171347
pointers[stripe++] = kmap_local_paddr(rbio_qstripe_paddr(rbio, sectornr));
13181348

@@ -1932,15 +1962,15 @@ static int recover_vertical(struct btrfs_raid_bio *rbio, int sector_nr,
19321962
if (ret < 0)
19331963
goto cleanup;
19341964

1935-
set_bit(rbio_stripe_sector_index(rbio, faila, sector_nr),
1965+
set_bit(rbio_sector_index(rbio, faila, sector_nr),
19361966
rbio->stripe_uptodate_bitmap);
19371967
}
19381968
if (failb >= 0) {
19391969
ret = verify_one_sector(rbio, failb, sector_nr);
19401970
if (ret < 0)
19411971
goto cleanup;
19421972

1943-
set_bit(rbio_stripe_sector_index(rbio, failb, sector_nr),
1973+
set_bit(rbio_sector_index(rbio, failb, sector_nr),
19441974
rbio->stripe_uptodate_bitmap);
19451975
}
19461976

@@ -2288,7 +2318,7 @@ static bool need_read_stripe_sectors(struct btrfs_raid_bio *rbio)
22882318
int i;
22892319

22902320
for (i = 0; i < rbio->nr_data * rbio->stripe_nsectors; i++) {
2291-
phys_addr_t paddr = rbio->stripe_paddrs[i];
2321+
phys_addr_t paddr = rbio->stripe_paddrs[i * rbio->sector_nsteps];
22922322

22932323
/*
22942324
* We have a sector which doesn't have page nor uptodate,
@@ -2746,7 +2776,7 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
27462776
* The bio cache may have handed us an uptodate sector. If so,
27472777
* use it.
27482778
*/
2749-
if (test_bit(rbio_stripe_sector_index(rbio, stripe, sectornr),
2779+
if (test_bit(rbio_sector_index(rbio, stripe, sectornr),
27502780
rbio->stripe_uptodate_bitmap))
27512781
continue;
27522782

fs/btrfs/raid56.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ enum btrfs_rbio_ops {
4848
* If there is no bio covering a sector, then btrfs_raid_bio::bio_paddrs[i] will
4949
* be INVALID_PADDR.
5050
*
51-
* The length of each entry in bio_paddrs[] is sectorsize.
51+
* The length of each entry in bio_paddrs[] is a step (aka, min(sectorsize, PAGE_SIZE)).
5252
*
5353
* [PAGES FOR INTERNAL USAGES]
5454
* Pages not covered by any bio or belonging to P/Q stripes are stored in
@@ -70,7 +70,7 @@ enum btrfs_rbio_ops {
7070
* If the corresponding page of stripe_paddrs[i] is not allocated, the value of
7171
* stripe_paddrs[i] will be INVALID_PADDR.
7272
*
73-
* The length of each entry in stripe_paddrs[] is sectorsize.
73+
* The length of each entry in stripe_paddrs[] is a step.
7474
*
7575
* [LOCATING A SECTOR]
7676
* To locate a sector for IO, we need the following info:
@@ -83,7 +83,15 @@ enum btrfs_rbio_ops {
8383
* Starts from 0 (representing the first sector of the stripe), ends
8484
* at BTRFS_STRIPE_LEN / sectorsize - 1.
8585
*
86-
* All existing bitmaps are based on sector numbers.
86+
* - step_nr
87+
* A step is min(sector_size, PAGE_SIZE).
88+
*
89+
* Starts from 0 (representing the first step of the sector), ends
90+
* at @sector_nsteps - 1.
91+
*
92+
* For most call sites they do not need to bother this parameter.
93+
* It is for bs > ps support and only for vertical stripe related works.
94+
* (e.g. RMW/recover)
8795
*
8896
* - from which array
8997
* Whether grabbing from stripe_paddrs[] (aka, internal pages) or from the
@@ -151,6 +159,14 @@ struct btrfs_raid_bio {
151159
/* How many sectors there are for each stripe */
152160
u8 stripe_nsectors;
153161

162+
/*
163+
* How many steps there are for one sector.
164+
*
165+
* For bs > ps cases, it's sectorsize / PAGE_SIZE.
166+
* For bs <= ps cases, it's always 1.
167+
*/
168+
u8 sector_nsteps;
169+
154170
/* Stripe number that we're scrubbing */
155171
u8 scrubp;
156172

0 commit comments

Comments
 (0)