Skip to content

Commit c73e680

Browse files
Sungjong Seonamjaejeon
authored andcommitted
exfat: call bh_read in get_block only when necessary
With commit 11a347f ("exfat: change to get file size from DataLength"), exfat_get_block() can now handle valid_size. However, most partial unwritten blocks that could be mapped with other blocks are being inefficiently processed separately as individual blocks. Except for partial unwritten blocks that require independent processing, let's handle them simply as before. Signed-off-by: Sungjong Seo <sj1557.seo@samsung.com> Reviewed-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent 59c30e3 commit c73e680

File tree

1 file changed

+77
-82
lines changed

1 file changed

+77
-82
lines changed

fs/exfat/inode.c

Lines changed: 77 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,11 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
274274
sector_t last_block;
275275
sector_t phys = 0;
276276
sector_t valid_blks;
277+
loff_t i_size;
277278

278279
mutex_lock(&sbi->s_lock);
279-
last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb);
280+
i_size = i_size_read(inode);
281+
last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size, sb);
280282
if (iblock >= last_block && !create)
281283
goto done;
282284

@@ -305,102 +307,95 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
305307
if (buffer_delay(bh_result))
306308
clear_buffer_delay(bh_result);
307309

308-
if (create) {
310+
/*
311+
* In most cases, we just need to set bh_result to mapped, unmapped
312+
* or new status as follows:
313+
* 1. i_size == valid_size
314+
* 2. write case (create == 1)
315+
* 3. direct_read (!bh_result->b_folio)
316+
* -> the unwritten part will be zeroed in exfat_direct_IO()
317+
*
318+
* Otherwise, in the case of buffered read, it is necessary to take
319+
* care the last nested block if valid_size is not equal to i_size.
320+
*/
321+
if (i_size == ei->valid_size || create || !bh_result->b_folio)
309322
valid_blks = EXFAT_B_TO_BLK_ROUND_UP(ei->valid_size, sb);
323+
else
324+
valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
310325

311-
if (iblock + max_blocks < valid_blks) {
312-
/* The range has been written, map it */
313-
goto done;
314-
} else if (iblock < valid_blks) {
315-
/*
316-
* The range has been partially written,
317-
* map the written part.
318-
*/
319-
max_blocks = valid_blks - iblock;
320-
goto done;
321-
}
326+
/* The range has been fully written, map it */
327+
if (iblock + max_blocks < valid_blks)
328+
goto done;
322329

323-
/* The area has not been written, map and mark as new. */
324-
set_buffer_new(bh_result);
330+
/* The range has been partially written, map the written part */
331+
if (iblock < valid_blks) {
332+
max_blocks = valid_blks - iblock;
333+
goto done;
334+
}
325335

336+
/* The area has not been written, map and mark as new for create case */
337+
if (create) {
338+
set_buffer_new(bh_result);
326339
ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
327340
mark_inode_dirty(inode);
328-
} else {
329-
valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
341+
goto done;
342+
}
330343

331-
if (iblock + max_blocks < valid_blks) {
332-
/* The range has been written, map it */
333-
goto done;
334-
} else if (iblock < valid_blks) {
335-
/*
336-
* The area has been partially written,
337-
* map the written part.
338-
*/
339-
max_blocks = valid_blks - iblock;
344+
/*
345+
* The area has just one block partially written.
346+
* In that case, we should read and fill the unwritten part of
347+
* a block with zero.
348+
*/
349+
if (bh_result->b_folio && iblock == valid_blks &&
350+
(ei->valid_size & (sb->s_blocksize - 1))) {
351+
loff_t size, pos;
352+
void *addr;
353+
354+
max_blocks = 1;
355+
356+
/*
357+
* No buffer_head is allocated.
358+
* (1) bmap: It's enough to set blocknr without I/O.
359+
* (2) read: The unwritten part should be filled with zero.
360+
* If a folio does not have any buffers,
361+
* let's returns -EAGAIN to fallback to
362+
* block_read_full_folio() for per-bh IO.
363+
*/
364+
if (!folio_buffers(bh_result->b_folio)) {
365+
err = -EAGAIN;
340366
goto done;
341-
} else if (iblock == valid_blks &&
342-
(ei->valid_size & (sb->s_blocksize - 1))) {
343-
/*
344-
* The block has been partially written,
345-
* zero the unwritten part and map the block.
346-
*/
347-
loff_t size, pos;
348-
void *addr;
349-
350-
max_blocks = 1;
351-
352-
/*
353-
* For direct read, the unwritten part will be zeroed in
354-
* exfat_direct_IO()
355-
*/
356-
if (!bh_result->b_folio)
357-
goto done;
358-
359-
/*
360-
* No buffer_head is allocated.
361-
* (1) bmap: It's enough to fill bh_result without I/O.
362-
* (2) read: The unwritten part should be filled with 0
363-
* If a folio does not have any buffers,
364-
* let's returns -EAGAIN to fallback to
365-
* per-bh IO like block_read_full_folio().
366-
*/
367-
if (!folio_buffers(bh_result->b_folio)) {
368-
err = -EAGAIN;
369-
goto done;
370-
}
367+
}
371368

372-
pos = EXFAT_BLK_TO_B(iblock, sb);
373-
size = ei->valid_size - pos;
374-
addr = folio_address(bh_result->b_folio) +
375-
offset_in_folio(bh_result->b_folio, pos);
369+
pos = EXFAT_BLK_TO_B(iblock, sb);
370+
size = ei->valid_size - pos;
371+
addr = folio_address(bh_result->b_folio) +
372+
offset_in_folio(bh_result->b_folio, pos);
376373

377-
/* Check if bh->b_data points to proper addr in folio */
378-
if (bh_result->b_data != addr) {
379-
exfat_fs_error_ratelimit(sb,
374+
/* Check if bh->b_data points to proper addr in folio */
375+
if (bh_result->b_data != addr) {
376+
exfat_fs_error_ratelimit(sb,
380377
"b_data(%p) != folio_addr(%p)",
381378
bh_result->b_data, addr);
382-
err = -EINVAL;
383-
goto done;
384-
}
385-
386-
/* Read a block */
387-
err = bh_read(bh_result, 0);
388-
if (err < 0)
389-
goto done;
379+
err = -EINVAL;
380+
goto done;
381+
}
390382

391-
/* Zero unwritten part of a block */
392-
memset(bh_result->b_data + size, 0,
393-
bh_result->b_size - size);
383+
/* Read a block */
384+
err = bh_read(bh_result, 0);
385+
if (err < 0)
386+
goto done;
394387

395-
err = 0;
396-
} else {
397-
/*
398-
* The range has not been written, clear the mapped flag
399-
* to only zero the cache and do not read from disk.
400-
*/
401-
clear_buffer_mapped(bh_result);
402-
}
388+
/* Zero unwritten part of a block */
389+
memset(bh_result->b_data + size, 0, bh_result->b_size - size);
390+
err = 0;
391+
goto done;
403392
}
393+
394+
/*
395+
* The area has not been written, clear mapped for read/bmap cases.
396+
* If so, it will be filled with zero without reading from disk.
397+
*/
398+
clear_buffer_mapped(bh_result);
404399
done:
405400
bh_result->b_size = EXFAT_BLK_TO_B(max_blocks, sb);
406401
if (err < 0)

0 commit comments

Comments
 (0)