Skip to content

Commit 0d0a60c

Browse files
committed
Merge branch 'rh/dioread-nolock-1k' into dev
2 parents 7855a57 + c33fbe8 commit 0d0a60c

File tree

5 files changed

+208
-110
lines changed

5 files changed

+208
-110
lines changed

fs/ext4/ext4.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ struct ext4_system_blocks {
198198
*/
199199
#define EXT4_IO_END_UNWRITTEN 0x0001
200200

201+
struct ext4_io_end_vec {
202+
struct list_head list; /* list of io_end_vec */
203+
loff_t offset; /* offset in the file */
204+
ssize_t size; /* size of the extent */
205+
};
206+
201207
/*
202208
* For converting unwritten extents on a work queue. 'handle' is used for
203209
* buffered writeback.
@@ -211,8 +217,7 @@ typedef struct ext4_io_end {
211217
* bios covering the extent */
212218
unsigned int flag; /* unwritten or not */
213219
atomic_t count; /* reference counter */
214-
loff_t offset; /* offset in the file */
215-
ssize_t size; /* size of the extent */
220+
struct list_head list_vec; /* list of ext4_io_end_vec */
216221
} ext4_io_end_t;
217222

218223
struct ext4_io_submit {
@@ -3264,6 +3269,8 @@ extern long ext4_fallocate(struct file *file, int mode, loff_t offset,
32643269
loff_t len);
32653270
extern int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
32663271
loff_t offset, ssize_t len);
3272+
extern int ext4_convert_unwritten_io_end_vec(handle_t *handle,
3273+
ext4_io_end_t *io_end);
32673274
extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
32683275
struct ext4_map_blocks *map, int flags);
32693276
extern int ext4_ext_calc_metadata_amount(struct inode *inode,
@@ -3322,6 +3329,8 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io,
33223329
int len,
33233330
struct writeback_control *wbc,
33243331
bool keep_towrite);
3332+
extern struct ext4_io_end_vec *ext4_alloc_io_end_vec(ext4_io_end_t *io_end);
3333+
extern struct ext4_io_end_vec *ext4_last_io_end_vec(ext4_io_end_t *io_end);
33253334

33263335
/* mmp.c */
33273336
extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);

fs/ext4/extents.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4962,23 +4962,13 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
49624962
int ret = 0;
49634963
int ret2 = 0;
49644964
struct ext4_map_blocks map;
4965-
unsigned int credits, blkbits = inode->i_blkbits;
4965+
unsigned int blkbits = inode->i_blkbits;
4966+
unsigned int credits = 0;
49664967

49674968
map.m_lblk = offset >> blkbits;
49684969
max_blocks = EXT4_MAX_BLOCKS(len, offset, blkbits);
49694970

4970-
/*
4971-
* This is somewhat ugly but the idea is clear: When transaction is
4972-
* reserved, everything goes into it. Otherwise we rather start several
4973-
* smaller transactions for conversion of each extent separately.
4974-
*/
4975-
if (handle) {
4976-
handle = ext4_journal_start_reserved(handle,
4977-
EXT4_HT_EXT_CONVERT);
4978-
if (IS_ERR(handle))
4979-
return PTR_ERR(handle);
4980-
credits = 0;
4981-
} else {
4971+
if (!handle) {
49824972
/*
49834973
* credits to insert 1 extent into extent tree
49844974
*/
@@ -5009,11 +4999,40 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
50094999
if (ret <= 0 || ret2)
50105000
break;
50115001
}
5012-
if (!credits)
5013-
ret2 = ext4_journal_stop(handle);
50145002
return ret > 0 ? ret2 : ret;
50155003
}
50165004

5005+
int ext4_convert_unwritten_io_end_vec(handle_t *handle, ext4_io_end_t *io_end)
5006+
{
5007+
int ret, err = 0;
5008+
struct ext4_io_end_vec *io_end_vec;
5009+
5010+
/*
5011+
* This is somewhat ugly but the idea is clear: When transaction is
5012+
* reserved, everything goes into it. Otherwise we rather start several
5013+
* smaller transactions for conversion of each extent separately.
5014+
*/
5015+
if (handle) {
5016+
handle = ext4_journal_start_reserved(handle,
5017+
EXT4_HT_EXT_CONVERT);
5018+
if (IS_ERR(handle))
5019+
return PTR_ERR(handle);
5020+
}
5021+
5022+
list_for_each_entry(io_end_vec, &io_end->list_vec, list) {
5023+
ret = ext4_convert_unwritten_extents(handle, io_end->inode,
5024+
io_end_vec->offset,
5025+
io_end_vec->size);
5026+
if (ret)
5027+
break;
5028+
}
5029+
5030+
if (handle)
5031+
err = ext4_journal_stop(handle);
5032+
5033+
return ret < 0 ? ret : err;
5034+
}
5035+
50175036
/*
50185037
* If newes is not existing extent (newes->ec_pblk equals zero) find
50195038
* delayed extent at start of newes and update newes accordingly and

fs/ext4/inode.c

Lines changed: 90 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,6 +2340,75 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd,
23402340
return lblk < blocks;
23412341
}
23422342

2343+
/*
2344+
* mpage_process_page - update page buffers corresponding to changed extent and
2345+
* may submit fully mapped page for IO
2346+
*
2347+
* @mpd - description of extent to map, on return next extent to map
2348+
* @m_lblk - logical block mapping.
2349+
* @m_pblk - corresponding physical mapping.
2350+
* @map_bh - determines on return whether this page requires any further
2351+
* mapping or not.
2352+
* Scan given page buffers corresponding to changed extent and update buffer
2353+
* state according to new extent state.
2354+
* We map delalloc buffers to their physical location, clear unwritten bits.
2355+
* If the given page is not fully mapped, we update @map to the next extent in
2356+
* the given page that needs mapping & return @map_bh as true.
2357+
*/
2358+
static int mpage_process_page(struct mpage_da_data *mpd, struct page *page,
2359+
ext4_lblk_t *m_lblk, ext4_fsblk_t *m_pblk,
2360+
bool *map_bh)
2361+
{
2362+
struct buffer_head *head, *bh;
2363+
ext4_io_end_t *io_end = mpd->io_submit.io_end;
2364+
ext4_lblk_t lblk = *m_lblk;
2365+
ext4_fsblk_t pblock = *m_pblk;
2366+
int err = 0;
2367+
int blkbits = mpd->inode->i_blkbits;
2368+
ssize_t io_end_size = 0;
2369+
struct ext4_io_end_vec *io_end_vec = ext4_last_io_end_vec(io_end);
2370+
2371+
bh = head = page_buffers(page);
2372+
do {
2373+
if (lblk < mpd->map.m_lblk)
2374+
continue;
2375+
if (lblk >= mpd->map.m_lblk + mpd->map.m_len) {
2376+
/*
2377+
* Buffer after end of mapped extent.
2378+
* Find next buffer in the page to map.
2379+
*/
2380+
mpd->map.m_len = 0;
2381+
mpd->map.m_flags = 0;
2382+
io_end_vec->size += io_end_size;
2383+
io_end_size = 0;
2384+
2385+
err = mpage_process_page_bufs(mpd, head, bh, lblk);
2386+
if (err > 0)
2387+
err = 0;
2388+
if (!err && mpd->map.m_len && mpd->map.m_lblk > lblk) {
2389+
io_end_vec = ext4_alloc_io_end_vec(io_end);
2390+
io_end_vec->offset = mpd->map.m_lblk << blkbits;
2391+
}
2392+
*map_bh = true;
2393+
goto out;
2394+
}
2395+
if (buffer_delay(bh)) {
2396+
clear_buffer_delay(bh);
2397+
bh->b_blocknr = pblock++;
2398+
}
2399+
clear_buffer_unwritten(bh);
2400+
io_end_size += (1 << blkbits);
2401+
} while (lblk++, (bh = bh->b_this_page) != head);
2402+
2403+
io_end_vec->size += io_end_size;
2404+
io_end_size = 0;
2405+
*map_bh = false;
2406+
out:
2407+
*m_lblk = lblk;
2408+
*m_pblk = pblock;
2409+
return err;
2410+
}
2411+
23432412
/*
23442413
* mpage_map_buffers - update buffers corresponding to changed extent and
23452414
* submit fully mapped pages for IO
@@ -2359,12 +2428,12 @@ static int mpage_map_and_submit_buffers(struct mpage_da_data *mpd)
23592428
struct pagevec pvec;
23602429
int nr_pages, i;
23612430
struct inode *inode = mpd->inode;
2362-
struct buffer_head *head, *bh;
23632431
int bpp_bits = PAGE_SHIFT - inode->i_blkbits;
23642432
pgoff_t start, end;
23652433
ext4_lblk_t lblk;
2366-
sector_t pblock;
2434+
ext4_fsblk_t pblock;
23672435
int err;
2436+
bool map_bh = false;
23682437

23692438
start = mpd->map.m_lblk >> bpp_bits;
23702439
end = (mpd->map.m_lblk + mpd->map.m_len - 1) >> bpp_bits;
@@ -2380,57 +2449,29 @@ static int mpage_map_and_submit_buffers(struct mpage_da_data *mpd)
23802449
for (i = 0; i < nr_pages; i++) {
23812450
struct page *page = pvec.pages[i];
23822451

2383-
bh = head = page_buffers(page);
2384-
do {
2385-
if (lblk < mpd->map.m_lblk)
2386-
continue;
2387-
if (lblk >= mpd->map.m_lblk + mpd->map.m_len) {
2388-
/*
2389-
* Buffer after end of mapped extent.
2390-
* Find next buffer in the page to map.
2391-
*/
2392-
mpd->map.m_len = 0;
2393-
mpd->map.m_flags = 0;
2394-
/*
2395-
* FIXME: If dioread_nolock supports
2396-
* blocksize < pagesize, we need to make
2397-
* sure we add size mapped so far to
2398-
* io_end->size as the following call
2399-
* can submit the page for IO.
2400-
*/
2401-
err = mpage_process_page_bufs(mpd, head,
2402-
bh, lblk);
2403-
pagevec_release(&pvec);
2404-
if (err > 0)
2405-
err = 0;
2406-
return err;
2407-
}
2408-
if (buffer_delay(bh)) {
2409-
clear_buffer_delay(bh);
2410-
bh->b_blocknr = pblock++;
2411-
}
2412-
clear_buffer_unwritten(bh);
2413-
} while (lblk++, (bh = bh->b_this_page) != head);
2414-
2452+
err = mpage_process_page(mpd, page, &lblk, &pblock,
2453+
&map_bh);
24152454
/*
2416-
* FIXME: This is going to break if dioread_nolock
2417-
* supports blocksize < pagesize as we will try to
2418-
* convert potentially unmapped parts of inode.
2455+
* If map_bh is true, means page may require further bh
2456+
* mapping, or maybe the page was submitted for IO.
2457+
* So we return to call further extent mapping.
24192458
*/
2420-
mpd->io_submit.io_end->size += PAGE_SIZE;
2459+
if (err < 0 || map_bh == true)
2460+
goto out;
24212461
/* Page fully mapped - let IO run! */
24222462
err = mpage_submit_page(mpd, page);
2423-
if (err < 0) {
2424-
pagevec_release(&pvec);
2425-
return err;
2426-
}
2463+
if (err < 0)
2464+
goto out;
24272465
}
24282466
pagevec_release(&pvec);
24292467
}
24302468
/* Extent fully mapped and matches with page boundary. We are done. */
24312469
mpd->map.m_len = 0;
24322470
mpd->map.m_flags = 0;
24332471
return 0;
2472+
out:
2473+
pagevec_release(&pvec);
2474+
return err;
24342475
}
24352476

24362477
static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
@@ -2510,9 +2551,10 @@ static int mpage_map_and_submit_extent(handle_t *handle,
25102551
int err;
25112552
loff_t disksize;
25122553
int progress = 0;
2554+
ext4_io_end_t *io_end = mpd->io_submit.io_end;
2555+
struct ext4_io_end_vec *io_end_vec = ext4_alloc_io_end_vec(io_end);
25132556

2514-
mpd->io_submit.io_end->offset =
2515-
((loff_t)map->m_lblk) << inode->i_blkbits;
2557+
io_end_vec->offset = ((loff_t)map->m_lblk) << inode->i_blkbits;
25162558
do {
25172559
err = mpage_map_one_extent(handle, mpd);
25182560
if (err < 0) {
@@ -3613,6 +3655,7 @@ static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
36133655
ssize_t size, void *private)
36143656
{
36153657
ext4_io_end_t *io_end = private;
3658+
struct ext4_io_end_vec *io_end_vec;
36163659

36173660
/* if not async direct IO just return */
36183661
if (!io_end)
@@ -3630,8 +3673,9 @@ static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
36303673
ext4_clear_io_unwritten_flag(io_end);
36313674
size = 0;
36323675
}
3633-
io_end->offset = offset;
3634-
io_end->size = size;
3676+
io_end_vec = ext4_alloc_io_end_vec(io_end);
3677+
io_end_vec->offset = offset;
3678+
io_end_vec->size = size;
36353679
ext4_put_io_end(io_end);
36363680

36373681
return 0;

0 commit comments

Comments
 (0)