@@ -65,7 +65,11 @@ static inline void kc_unxlate_dev_mem_ptr(phys_addr_t phys, void *virt)
65
65
#endif
66
66
67
67
static LIST_HEAD (kclist_head );
68
- static DECLARE_RWSEM (kclist_lock );
68
+ static int kcore_nphdr ;
69
+ static size_t kcore_phdrs_len ;
70
+ static size_t kcore_notes_len ;
71
+ static size_t kcore_data_offset ;
72
+ DEFINE_STATIC_PERCPU_RWSEM (kclist_lock );
69
73
static int kcore_need_update = 1 ;
70
74
71
75
/*
@@ -101,33 +105,32 @@ void __init kclist_add(struct kcore_list *new, void *addr, size_t size,
101
105
list_add_tail (& new -> list , & kclist_head );
102
106
}
103
107
104
- static size_t get_kcore_size (int * nphdr , size_t * phdrs_len , size_t * notes_len ,
105
- size_t * data_offset )
108
+ static void update_kcore_size (void )
106
109
{
107
110
size_t try , size ;
108
111
struct kcore_list * m ;
109
112
110
- * nphdr = 1 ; /* PT_NOTE */
113
+ kcore_nphdr = 1 ; /* PT_NOTE */
111
114
size = 0 ;
112
115
113
116
list_for_each_entry (m , & kclist_head , list ) {
114
117
try = kc_vaddr_to_offset ((size_t )m -> addr + m -> size );
115
118
if (try > size )
116
119
size = try ;
117
- * nphdr = * nphdr + 1 ;
120
+ kcore_nphdr ++ ;
118
121
}
119
122
120
- * phdrs_len = * nphdr * sizeof (struct elf_phdr );
121
- * notes_len = (4 * sizeof (struct elf_note ) +
122
- 3 * ALIGN (sizeof (CORE_STR ), 4 ) +
123
- VMCOREINFO_NOTE_NAME_BYTES +
124
- ALIGN (sizeof (struct elf_prstatus ), 4 ) +
125
- ALIGN (sizeof (struct elf_prpsinfo ), 4 ) +
126
- ALIGN (arch_task_struct_size , 4 ) +
127
- ALIGN (vmcoreinfo_size , 4 ));
128
- * data_offset = PAGE_ALIGN (sizeof (struct elfhdr ) + * phdrs_len +
129
- * notes_len );
130
- return * data_offset + size ;
123
+ kcore_phdrs_len = kcore_nphdr * sizeof (struct elf_phdr );
124
+ kcore_notes_len = (4 * sizeof (struct elf_note ) +
125
+ 3 * ALIGN (sizeof (CORE_STR ), 4 ) +
126
+ VMCOREINFO_NOTE_NAME_BYTES +
127
+ ALIGN (sizeof (struct elf_prstatus ), 4 ) +
128
+ ALIGN (sizeof (struct elf_prpsinfo ), 4 ) +
129
+ ALIGN (arch_task_struct_size , 4 ) +
130
+ ALIGN (vmcoreinfo_size , 4 ));
131
+ kcore_data_offset = PAGE_ALIGN (sizeof (struct elfhdr ) + kcore_phdrs_len +
132
+ kcore_notes_len );
133
+ proc_root_kcore -> size = kcore_data_offset + size ;
131
134
}
132
135
133
136
#ifdef CONFIG_HIGHMEM
@@ -270,12 +273,10 @@ static int kcore_update_ram(void)
270
273
{
271
274
LIST_HEAD (list );
272
275
LIST_HEAD (garbage );
273
- int nphdr ;
274
- size_t phdrs_len , notes_len , data_offset ;
275
276
struct kcore_list * tmp , * pos ;
276
277
int ret = 0 ;
277
278
278
- down_write (& kclist_lock );
279
+ percpu_down_write (& kclist_lock );
279
280
if (!xchg (& kcore_need_update , 0 ))
280
281
goto out ;
281
282
@@ -293,11 +294,10 @@ static int kcore_update_ram(void)
293
294
}
294
295
list_splice_tail (& list , & kclist_head );
295
296
296
- proc_root_kcore -> size = get_kcore_size (& nphdr , & phdrs_len , & notes_len ,
297
- & data_offset );
297
+ update_kcore_size ();
298
298
299
299
out :
300
- up_write (& kclist_lock );
300
+ percpu_up_write (& kclist_lock );
301
301
list_for_each_entry_safe (pos , tmp , & garbage , list ) {
302
302
list_del (& pos -> list );
303
303
kfree (pos );
@@ -326,27 +326,24 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
326
326
struct file * file = iocb -> ki_filp ;
327
327
char * buf = file -> private_data ;
328
328
loff_t * fpos = & iocb -> ki_pos ;
329
- size_t phdrs_offset , notes_offset , data_offset ;
329
+ size_t phdrs_offset , notes_offset ;
330
330
size_t page_offline_frozen = 1 ;
331
- size_t phdrs_len , notes_len ;
332
331
struct kcore_list * m ;
333
332
size_t tsz ;
334
- int nphdr ;
335
333
unsigned long start ;
336
334
size_t buflen = iov_iter_count (iter );
337
335
size_t orig_buflen = buflen ;
338
336
int ret = 0 ;
339
337
340
- down_read (& kclist_lock );
338
+ percpu_down_read (& kclist_lock );
341
339
/*
342
340
* Don't race against drivers that set PageOffline() and expect no
343
341
* further page access.
344
342
*/
345
343
page_offline_freeze ();
346
344
347
- get_kcore_size (& nphdr , & phdrs_len , & notes_len , & data_offset );
348
345
phdrs_offset = sizeof (struct elfhdr );
349
- notes_offset = phdrs_offset + phdrs_len ;
346
+ notes_offset = phdrs_offset + kcore_phdrs_len ;
350
347
351
348
/* ELF file header. */
352
349
if (buflen && * fpos < sizeof (struct elfhdr )) {
@@ -368,7 +365,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
368
365
.e_flags = ELF_CORE_EFLAGS ,
369
366
.e_ehsize = sizeof (struct elfhdr ),
370
367
.e_phentsize = sizeof (struct elf_phdr ),
371
- .e_phnum = nphdr ,
368
+ .e_phnum = kcore_nphdr ,
372
369
};
373
370
374
371
tsz = min_t (size_t , buflen , sizeof (struct elfhdr ) - * fpos );
@@ -382,24 +379,25 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
382
379
}
383
380
384
381
/* ELF program headers. */
385
- if (buflen && * fpos < phdrs_offset + phdrs_len ) {
382
+ if (buflen && * fpos < phdrs_offset + kcore_phdrs_len ) {
386
383
struct elf_phdr * phdrs , * phdr ;
387
384
388
- phdrs = kzalloc (phdrs_len , GFP_KERNEL );
385
+ phdrs = kzalloc (kcore_phdrs_len , GFP_KERNEL );
389
386
if (!phdrs ) {
390
387
ret = - ENOMEM ;
391
388
goto out ;
392
389
}
393
390
394
391
phdrs [0 ].p_type = PT_NOTE ;
395
392
phdrs [0 ].p_offset = notes_offset ;
396
- phdrs [0 ].p_filesz = notes_len ;
393
+ phdrs [0 ].p_filesz = kcore_notes_len ;
397
394
398
395
phdr = & phdrs [1 ];
399
396
list_for_each_entry (m , & kclist_head , list ) {
400
397
phdr -> p_type = PT_LOAD ;
401
398
phdr -> p_flags = PF_R | PF_W | PF_X ;
402
- phdr -> p_offset = kc_vaddr_to_offset (m -> addr ) + data_offset ;
399
+ phdr -> p_offset = kc_vaddr_to_offset (m -> addr )
400
+ + kcore_data_offset ;
403
401
phdr -> p_vaddr = (size_t )m -> addr ;
404
402
if (m -> type == KCORE_RAM )
405
403
phdr -> p_paddr = __pa (m -> addr );
@@ -412,7 +410,8 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
412
410
phdr ++ ;
413
411
}
414
412
415
- tsz = min_t (size_t , buflen , phdrs_offset + phdrs_len - * fpos );
413
+ tsz = min_t (size_t , buflen ,
414
+ phdrs_offset + kcore_phdrs_len - * fpos );
416
415
if (copy_to_iter ((char * )phdrs + * fpos - phdrs_offset , tsz ,
417
416
iter ) != tsz ) {
418
417
kfree (phdrs );
@@ -426,7 +425,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
426
425
}
427
426
428
427
/* ELF note segment. */
429
- if (buflen && * fpos < notes_offset + notes_len ) {
428
+ if (buflen && * fpos < notes_offset + kcore_notes_len ) {
430
429
struct elf_prstatus prstatus = {};
431
430
struct elf_prpsinfo prpsinfo = {
432
431
.pr_sname = 'R' ,
@@ -438,7 +437,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
438
437
strscpy (prpsinfo .pr_psargs , saved_command_line ,
439
438
sizeof (prpsinfo .pr_psargs ));
440
439
441
- notes = kzalloc (notes_len , GFP_KERNEL );
440
+ notes = kzalloc (kcore_notes_len , GFP_KERNEL );
442
441
if (!notes ) {
443
442
ret = - ENOMEM ;
444
443
goto out ;
@@ -459,9 +458,10 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
459
458
*/
460
459
append_kcore_note (notes , & i , VMCOREINFO_NOTE_NAME , 0 ,
461
460
vmcoreinfo_data ,
462
- min (vmcoreinfo_size , notes_len - i ));
461
+ min (vmcoreinfo_size , kcore_notes_len - i ));
463
462
464
- tsz = min_t (size_t , buflen , notes_offset + notes_len - * fpos );
463
+ tsz = min_t (size_t , buflen ,
464
+ notes_offset + kcore_notes_len - * fpos );
465
465
if (copy_to_iter (notes + * fpos - notes_offset , tsz , iter ) != tsz ) {
466
466
kfree (notes );
467
467
ret = - EFAULT ;
@@ -477,7 +477,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
477
477
* Check to see if our file offset matches with any of
478
478
* the addresses in the elf_phdr on our list.
479
479
*/
480
- start = kc_offset_to_vaddr (* fpos - data_offset );
480
+ start = kc_offset_to_vaddr (* fpos - kcore_data_offset );
481
481
if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK ))) > buflen )
482
482
tsz = buflen ;
483
483
@@ -626,7 +626,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
626
626
627
627
out :
628
628
page_offline_thaw ();
629
- up_read (& kclist_lock );
629
+ percpu_up_read (& kclist_lock );
630
630
if (ret )
631
631
return ret ;
632
632
return orig_buflen - buflen ;
@@ -663,6 +663,7 @@ static int release_kcore(struct inode *inode, struct file *file)
663
663
}
664
664
665
665
static const struct proc_ops kcore_proc_ops = {
666
+ .proc_flags = PROC_ENTRY_PERMANENT ,
666
667
.proc_read_iter = read_kcore_iter ,
667
668
.proc_open = open_kcore ,
668
669
.proc_release = release_kcore ,
0 commit comments