Skip to content

Commit 605291e

Browse files
osandovbrauner
authored andcommitted
proc/kcore: use percpu_rw_semaphore for kclist_lock
The list of memory ranges for /proc/kcore is protected by a rw_semaphore. We lock it for reading on every read from /proc/kcore. This is very heavy, especially since it is rarely locked for writing. Since we want to strongly favor read lock performance, convert it to a percpu_rw_semaphore. I also experimented with percpu_ref and SRCU, but this change was the simplest and the fastest. In my benchmark, this reduces the time per read by yet another 20 nanoseconds on top of the previous two changes, from 195 nanoseconds per read to 175. Link: osandov/drgn#106 Signed-off-by: Omar Sandoval <[email protected]> Link: https://lore.kernel.org/r/83a3b235b4bcc3b8aef7c533e0657f4d7d5d35ae.1731115587.git.osandov@fb.com Signed-off-by: Christian Brauner <[email protected]>
1 parent 680e029 commit 605291e

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

fs/proc/kcore.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int kcore_nphdr;
6969
static size_t kcore_phdrs_len;
7070
static size_t kcore_notes_len;
7171
static size_t kcore_data_offset;
72-
static DECLARE_RWSEM(kclist_lock);
72+
DEFINE_STATIC_PERCPU_RWSEM(kclist_lock);
7373
static int kcore_need_update = 1;
7474

7575
/*
@@ -276,7 +276,7 @@ static int kcore_update_ram(void)
276276
struct kcore_list *tmp, *pos;
277277
int ret = 0;
278278

279-
down_write(&kclist_lock);
279+
percpu_down_write(&kclist_lock);
280280
if (!xchg(&kcore_need_update, 0))
281281
goto out;
282282

@@ -297,7 +297,7 @@ static int kcore_update_ram(void)
297297
update_kcore_size();
298298

299299
out:
300-
up_write(&kclist_lock);
300+
percpu_up_write(&kclist_lock);
301301
list_for_each_entry_safe(pos, tmp, &garbage, list) {
302302
list_del(&pos->list);
303303
kfree(pos);
@@ -335,7 +335,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
335335
size_t orig_buflen = buflen;
336336
int ret = 0;
337337

338-
down_read(&kclist_lock);
338+
percpu_down_read(&kclist_lock);
339339
/*
340340
* Don't race against drivers that set PageOffline() and expect no
341341
* further page access.
@@ -626,7 +626,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
626626

627627
out:
628628
page_offline_thaw();
629-
up_read(&kclist_lock);
629+
percpu_up_read(&kclist_lock);
630630
if (ret)
631631
return ret;
632632
return orig_buflen - buflen;

0 commit comments

Comments
 (0)