Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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/20231004165317.1061855-3-willy@infradead.org
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Richard Henderson <richard.henderson@linaro.org>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Matthew Wilcox (Oracle) and committed by
Andrew Morton
f45b494e 279d5fc3

+25 -12
+25 -12
fs/iomap/buffered-io.c
··· 29 29 * and I/O completions. 30 30 */ 31 31 struct iomap_folio_state { 32 - atomic_t read_bytes_pending; 33 - atomic_t write_bytes_pending; 34 32 spinlock_t state_lock; 33 + unsigned int read_bytes_pending; 34 + atomic_t write_bytes_pending; 35 35 36 36 /* 37 37 * Each block has two bits in this bitmap: ··· 183 183 184 184 if (!ifs) 185 185 return; 186 - WARN_ON_ONCE(atomic_read(&ifs->read_bytes_pending)); 186 + WARN_ON_ONCE(ifs->read_bytes_pending != 0); 187 187 WARN_ON_ONCE(atomic_read(&ifs->write_bytes_pending)); 188 188 WARN_ON_ONCE(ifs_is_fully_uptodate(folio, ifs) != 189 189 folio_test_uptodate(folio)); ··· 250 250 *lenp = plen; 251 251 } 252 252 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, 254 254 size_t len, int error) 255 255 { 256 256 struct iomap_folio_state *ifs = folio->private; 257 + bool uptodate = !error; 258 + bool finished = true; 257 259 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); 263 269 } 264 270 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) 266 276 folio_unlock(folio); 267 277 } 268 278 ··· 370 360 } 371 361 372 362 ctx->cur_folio_in_bio = true; 373 - if (ifs) 374 - atomic_add(plen, &ifs->read_bytes_pending); 363 + if (ifs) { 364 + spin_lock_irq(&ifs->state_lock); 365 + ifs->read_bytes_pending += plen; 366 + spin_unlock_irq(&ifs->state_lock); 367 + } 375 368 376 369 sector = iomap_sector(iomap, pos); 377 370 if (!ctx->bio ||