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.

[PATCH] blk: reduce locking

Change around locking a bit for a result of 1-2 less spin lock unlock pairs in
request submission paths.

Signed-off-by: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Jens Axboe <axboe@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Nick Piggin and committed by
Linus Torvalds
d6344532 450991bc

+19 -10
+19 -10
drivers/block/ll_rw_blk.c
··· 1867 1867 1868 1868 #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) 1869 1869 /* 1870 - * Get a free request, queue_lock must not be held 1870 + * Get a free request, queue_lock must be held. 1871 + * Returns NULL on failure, with queue_lock held. 1872 + * Returns !NULL on success, with queue_lock *not held*. 1871 1873 */ 1872 1874 static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, 1873 1875 int gfp_mask) 1874 1876 { 1875 1877 struct request *rq = NULL; 1876 1878 struct request_list *rl = &q->rq; 1877 - struct io_context *ioc = get_io_context(gfp_mask); 1879 + struct io_context *ioc = get_io_context(GFP_ATOMIC); 1878 1880 1879 1881 if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) 1880 1882 goto out; 1881 1883 1882 - spin_lock_irq(q->queue_lock); 1883 1884 if (rl->count[rw]+1 >= q->nr_requests) { 1884 1885 /* 1885 1886 * The queue will fill after this allocation, so set it as ··· 1908 1907 * The queue is full and the allocating process is not a 1909 1908 * "batcher", and not exempted by the IO scheduler 1910 1909 */ 1911 - spin_unlock_irq(q->queue_lock); 1912 1910 goto out; 1913 1911 } 1914 1912 ··· 1950 1950 if (unlikely(rl->count[rw] == 0)) 1951 1951 rl->starved[rw] = 1; 1952 1952 1953 - spin_unlock_irq(q->queue_lock); 1954 1953 goto out; 1955 1954 } 1956 1955 ··· 1966 1967 /* 1967 1968 * No available requests for this queue, unplug the device and wait for some 1968 1969 * requests to become available. 1970 + * 1971 + * Called with q->queue_lock held, and returns with it unlocked. 1969 1972 */ 1970 1973 static struct request *get_request_wait(request_queue_t *q, int rw, 1971 1974 struct bio *bio) ··· 1987 1986 if (!rq) { 1988 1987 struct io_context *ioc; 1989 1988 1990 - generic_unplug_device(q); 1989 + __generic_unplug_device(q); 1990 + spin_unlock_irq(q->queue_lock); 1991 1991 io_schedule(); 1992 1992 1993 1993 /* ··· 2000 1998 ioc = get_io_context(GFP_NOIO); 2001 1999 ioc_set_batching(q, ioc); 2002 2000 put_io_context(ioc); 2001 + 2002 + spin_lock_irq(q->queue_lock); 2003 2003 } 2004 2004 finish_wait(&rl->wait[rw], &wait); 2005 2005 } ··· 2015 2011 2016 2012 BUG_ON(rw != READ && rw != WRITE); 2017 2013 2018 - if (gfp_mask & __GFP_WAIT) 2014 + spin_lock_irq(q->queue_lock); 2015 + if (gfp_mask & __GFP_WAIT) { 2019 2016 rq = get_request_wait(q, rw, NULL); 2020 - else 2017 + } else { 2021 2018 rq = get_request(q, rw, NULL, gfp_mask); 2019 + if (!rq) 2020 + spin_unlock_irq(q->queue_lock); 2021 + } 2022 + /* q->queue_lock is unlocked at this point */ 2022 2023 2023 2024 return rq; 2024 2025 } 2025 - 2026 2026 EXPORT_SYMBOL(blk_get_request); 2027 2027 2028 2028 /** ··· 2613 2605 get_rq: 2614 2606 /* 2615 2607 * Grab a free request. This is might sleep but can not fail. 2608 + * Returns with the queue unlocked. 2616 2609 */ 2617 - spin_unlock_irq(q->queue_lock); 2618 2610 req = get_request_wait(q, rw, bio); 2611 + 2619 2612 /* 2620 2613 * After dropping the lock and possibly sleeping here, our request 2621 2614 * may now be mergeable after it had proven unmergeable (above).