Skip to content

Commit f45b494

Browse files
Matthew Wilcox (Oracle)akpm00
authored andcommitted
iomap: protect read_bytes_pending with the state_lock
Perform one atomic operation (acquiring the spinlock) instead of two (spinlock & atomic_sub) per read completion. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Cc: Albert Ou <[email protected]> Cc: Alexander Gordeev <[email protected]> Cc: Andreas Dilger <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Christophe Leroy <[email protected]> Cc: Geert Uytterhoeven <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Ivan Kokshaysky <[email protected]> Cc: Matt Turner <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Nicholas Piggin <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Richard Henderson <[email protected]> Cc: Sven Schnelle <[email protected]> Cc: "Theodore Ts'o" <[email protected]> Cc: Thomas Bogendoerfer <[email protected]> Cc: Vasily Gorbik <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 279d5fc commit f45b494

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

fs/iomap/buffered-io.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ typedef int (*iomap_punch_t)(struct inode *inode, loff_t offset, loff_t length);
2929
* and I/O completions.
3030
*/
3131
struct iomap_folio_state {
32-
atomic_t read_bytes_pending;
33-
atomic_t write_bytes_pending;
3432
spinlock_t state_lock;
33+
unsigned int read_bytes_pending;
34+
atomic_t write_bytes_pending;
3535

3636
/*
3737
* Each block has two bits in this bitmap:
@@ -183,7 +183,7 @@ static void ifs_free(struct folio *folio)
183183

184184
if (!ifs)
185185
return;
186-
WARN_ON_ONCE(atomic_read(&ifs->read_bytes_pending));
186+
WARN_ON_ONCE(ifs->read_bytes_pending != 0);
187187
WARN_ON_ONCE(atomic_read(&ifs->write_bytes_pending));
188188
WARN_ON_ONCE(ifs_is_fully_uptodate(folio, ifs) !=
189189
folio_test_uptodate(folio));
@@ -250,19 +250,29 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
250250
*lenp = plen;
251251
}
252252

253-
static void iomap_finish_folio_read(struct folio *folio, size_t offset,
253+
static void iomap_finish_folio_read(struct folio *folio, size_t off,
254254
size_t len, int error)
255255
{
256256
struct iomap_folio_state *ifs = folio->private;
257+
bool uptodate = !error;
258+
bool finished = true;
257259

258-
if (unlikely(error)) {
259-
folio_clear_uptodate(folio);
260-
folio_set_error(folio);
261-
} else {
262-
iomap_set_range_uptodate(folio, offset, len);
260+
if (ifs) {
261+
unsigned long flags;
262+
263+
spin_lock_irqsave(&ifs->state_lock, flags);
264+
if (!error)
265+
uptodate = ifs_set_range_uptodate(folio, ifs, off, len);
266+
ifs->read_bytes_pending -= len;
267+
finished = !ifs->read_bytes_pending;
268+
spin_unlock_irqrestore(&ifs->state_lock, flags);
263269
}
264270

265-
if (!ifs || atomic_sub_and_test(len, &ifs->read_bytes_pending))
271+
if (error)
272+
folio_set_error(folio);
273+
if (uptodate)
274+
folio_mark_uptodate(folio);
275+
if (finished)
266276
folio_unlock(folio);
267277
}
268278

@@ -360,8 +370,11 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
360370
}
361371

362372
ctx->cur_folio_in_bio = true;
363-
if (ifs)
364-
atomic_add(plen, &ifs->read_bytes_pending);
373+
if (ifs) {
374+
spin_lock_irq(&ifs->state_lock);
375+
ifs->read_bytes_pending += plen;
376+
spin_unlock_irq(&ifs->state_lock);
377+
}
365378

366379
sector = iomap_sector(iomap, pos);
367380
if (!ctx->bio ||

0 commit comments

Comments
 (0)