Refactoring and significantly reducing code complexity
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the WQ_UNBOUND attribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures like padata_cpumask, and deletion of parallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures like padata_list and padata_serial_queue
- Removal of padata_do_serial()
- padata automatically ensures the calling sequence.
Testing was conducted using ltp's pcrypt_aead01, and the execution time comparison between the old and new versions is as follows:
Old Version:
real 0m27.451s
user 0m0.031s
sys 0m0.260s
New Version:
real 0m21.351s
user 0m0.023s
sys 0m0.260s
--- crypto/pcrypt.c | 34 +- include/linux/padata.h | 95 +---- kernel/padata.c | 815 ++--------------------------------------- 3 files changed, 43 insertions(+), 901 deletions(-)
crypto/pcrypt.c +10 -24
@@ -70,8 +70,6 @@ static void pcrypt_aead_done(void *data, int err)struct padata_priv *padata =pcrypt_request_padata (preq); padata->info = err; - -padata_do_serial (padata); }static void pcrypt_aead_enc (struct padata_priv *padata)
@@ -86,7 +84,6 @@ static void pcrypt_aead_enc(struct padata_priv *padata)return ; padata->info = ret; -padata_do_serial (padata); }static int pcrypt_aead_encrypt (struct aead_request *req)
@@ -114,7 +111,7 @@ static int pcrypt_aead_encrypt(struct aead_request *req) req->cryptlen, req->iv);aead_request_set_ad (creq, req->assoclen); - err =padata_do_parallel (ictx->psenc, padata, &ctx->cb_cpu); + err =padata_do_parallel (ictx->psenc, padata);if (!err)return -EINPROGRESS ;
@@ -133,7 +130,6 @@ static void pcrypt_aead_dec(struct padata_priv *padata)return ; padata->info = ret; -padata_do_serial (padata); }static int pcrypt_aead_decrypt (struct aead_request *req)
@@ -161,7 +157,7 @@ static int pcrypt_aead_decrypt(struct aead_request *req) req->cryptlen, req->iv);aead_request_set_ad (creq, req->assoclen); - err =padata_do_parallel (ictx->psdec, padata, &ctx->cb_cpu); + err =padata_do_parallel (ictx->psdec, padata);if (!err)return -EINPROGRESS ;
@@ -304,31 +300,18 @@ static int pcrypt_create(struct crypto_template *tmpl, struct rtattr **tb)return -EINVAL ; } -static int pcrypt_sysfs_add (struct padata_instance *pinst,const char *name) -{ -int ret; - - pinst->kobj.kset = pcrypt_kset; - ret =kobject_add (&pinst->kobj,NULL ,"%s" , name); -if (!ret) -kobject_uevent (&pinst->kobj,KOBJ_ADD ); - -return ret; -} -static int pcrypt_init_padata (struct padata_instance **pinst,const char *name) {int ret = -ENOMEM ; +pr_info ("%s:%d %s\n" , __FILE__, __LINE__, __func__); *pinst =padata_alloc (name); +pr_info ("%s:%d %s\n" , __FILE__, __LINE__, __func__); +pr_info ("%s:%d %s *pinst=%p\n" , __FILE__, __LINE__, __func__, *pinst); +if (!*pinst)return ret; - - ret =pcrypt_sysfs_add (*pinst, name); -if (ret) -padata_free (*pinst); - -return ret; +return 0 ; }static struct crypto_template pcrypt_tmpl = {
@@ -344,15 +327,18 @@ static int __init pcrypt_init(void) pcrypt_kset =kset_create_and_add ("pcrypt" ,NULL , kernel_kobj);if (!pcrypt_kset) goto err; +pr_info ("%s:%d %s\n" , __FILE__, __LINE__, __func__); err =pcrypt_init_padata (&pencrypt,"pencrypt" );if (err) goto err_unreg_kset; +pr_info ("%s:%d %s\n" , __FILE__, __LINE__, __func__); err =pcrypt_init_padata (&pdecrypt,"pdecrypt" );if (err) goto err_deinit_pencrypt; +pr_info ("%s:%d %s\n" , __FILE__, __LINE__, __func__);return crypto_register_template (&pcrypt_tmpl); err_deinit_pencrypt:
include/linux/padata.h +7 -88
147 lines not on this page · raw message
kernel/padata.c +26 -789
942 lines not on this page · raw message
Signature · 1 line
2.40.0
Steffen Klassert
maintainerQuoted 9 lines · Wang Jinchao
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures likepadata_cpumask, and deletion ofparallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures likepadata_listandpadata_serial_queue
- Removal ofpadata_do_serial()
This removes all the logic that is needed to ensure that the parallelized objects return in the same order as they were before the parallelization. This change makes padata unusable for networking.
Quoted 11 lines · Steffen Klassert
Quoted 9 lines · Wang Jinchao
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures likepadata_cpumask, and deletion ofparallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures likepadata_listandpadata_serial_queue
- Removal ofpadata_do_serial()
Quoted 4 lines
This removes all the logic that is needed to ensure that the parallelized objects return in the same order as they were before the parallelization. This change makes padata unusable for networking.
The RFC use the following three to ensure serial timing sequence:
1. Use alloc_ordered_workqueue() to create a serial worker queue where serial() function runs. This ensures that serial() function executes as serial work was enqueued using queue_work().
2. Queue the serial work before enqueueing parallel work in padata_do_parallel(). This ensures the serial work follows the same order as the padata_do_parallel().
3. The serial work wait for completion of parallel_done, which will be complete()ed after the parallel() function within the parallel work.
This is just a design idea, because I am not familiar with IPsec, I haven't tested it in a real network environment yet.
Could you give me some clues on how to use pcrypt in an IPsec scenario?
Steffen Klassert
maintainerQuoted 19 lines · Wang Jinchao
Quoted 11 lines · Steffen Klassert
Quoted 9 lines · Wang Jinchao
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures likepadata_cpumask, and deletion ofparallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures likepadata_listandpadata_serial_queue
- Removal ofpadata_do_serial()Quoted 4 lines
This removes all the logic that is needed to ensure that the parallelized objects return in the same order as they were before the parallelization. This change makes padata unusable for networking.
The RFC use the following three to ensure serial timing sequence:
Quoted 7 lines
1. Use
alloc_ordered_workqueue()to create a serial worker queue whereserial()function runs. This ensures thatserial()function executes as serial work was enqueued usingqueue_work().
2. Queue the serial work before enqueueing parallel work inpadata_do_parallel(). This ensures the serial work follows the same order as thepadata_do_parallel().
3. The serial work wait for completion ofparallel_done, which will be complete()ed after theparallel()function within the parallel work.
I had a closer look to the padata codebase now. The logic to parallelize/serialize changed quite a bit since I wrote padata initially. I don't understand the new logic completely, so we need to rely on Daniels review for this.
Quoted 3 lines
This is just a design idea, because I am not familiar with IPsec, I haven't tested it in a real network environment yet.
Could you give me some clues on how to use pcrypt in an IPsec scenario?
pcrypt has performance gains if the cost of the crypto oreration is higher than the cost of moving the crypto request to another cpu. That was the case back in the days, but the situation changed since then. We now have hardware support for crypto, like aes-ni etc. So for hardware supported algorithms, pcrypt will not help much. But it is still interesting for crypto algorithms that are implemented in software only.
Here is how you can instantiate a pcrypted
algorithm:
----------------------------------------------------
You need to instantiate pcrypt before you can use it.
You need either crconf or the tcrypt module to instantiate pcrypt.
With crconf:
You can get crconf from https://sourceforge.net/projects/crconf/
After installing crconf do e.g.
crconf add driver "pcrypt(authenc(hmac(sha1-generic),cbc(aes-asm)))" type 3
With tcrypt:
modprobe tcrypt alg="pcrypt(authenc(hmac(sha1-generic),cbc(aes-asm)))" type=3
The modprobe will return with an error, don't worry about it, that's ok.
Once you've did one of the above, your /proc/crypto should show something like:
name : authenc(hmac(sha1),cbc(aes))
driver : pcrypt(authenc(hmac(sha1-generic),cbc(aes-asm)))
module : pcrypt
priority : 2100
refcnt : 1
selftest : passed
type : aead
async : yes
blocksize : 16
ivsize : 16
maxauthsize : 20
geniv : <built-in>
Now pcrypt is instantiated, e.g. all new IPsec states (that do hmac-sha1, cbc-aes) will use it.
Daniel Jordan
maintainerQuoted 2 lines · Wang Jinchao
This is just a design idea, because I am not familiar with IPsec, I haven't tested it in a real network environment yet.
Out of curiosity, what's your use case for padata?
Quoted 5 lines · Daniel Jordan
Quoted 2 lines · Wang Jinchao
This is just a design idea, because I am not familiar with IPsec, I haven't tested it in a real network environment yet.
Out of curiosity, what's your use case for padata?
When I wrote the rfc_v1 on September 28th, I only used the "pcrypt_aead01" test case from LTP. Thank you for you and Steffen's responses. I now have more test cases, but I haven't tested them yet.
Quoted 11 lines · Steffen Klassert
Quoted 9 lines · Wang Jinchao
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures likepadata_cpumask, and deletion ofparallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures likepadata_listandpadata_serial_queue
- Removal ofpadata_do_serial()
Quoted 4 lines
This removes all the logic that is needed to ensure that the parallelized objects return in the same order as they were before the parallelization. This change makes padata unusable for networking.
Hello Steffen,
I have constructed a scenario where parallel() time cost
is forced to be reversed , and then ensured the order using serial(). The tests have passed on a 32-core machine.
Can you please explain if my refactored approach guarantees the serial ordering?
Here is the code:
padata_test.c
--------------
```c
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/padata.h>
struct request {
struct padata_priv padata;
int seq;
struct completion done;
};
#define TEST_ARRAY_SIZE 200
#define PARALLEL_BASE_TIME 10
static int serial_cnt;
static int shuffled;
struct request requests[TEST_ARRAY_SIZE];
void parallel(struct padata_priv *padata) {
struct request *req = container_of(padata, struct request, padata);
// The smaller the req->seq number, the longer the delay time
// creating a reverse order.
mdelay((TEST_ARRAY_SIZE - req->seq) * PARALLEL_BASE_TIME);
msleep((TEST_ARRAY_SIZE - req->seq) * PARALLEL_BASE_TIME);
}
void serial(struct padata_priv *padata) {
struct request *req = container_of(padata, struct request, padata);
if (req->seq != serial_cnt)
shuffled = 1;
serial_cnt++;
complete(&req->done);
}
struct padata_instance *pinst;
struct padata_shell *ps;
static int __init padata_test_init(void) {
serial_cnt = 0;
shuffled = 0;
pinst = padata_alloc("padata_test");
if (!pinst)
return -ENOMEM;
ps = padata_alloc_shell(pinst);
for (int i = 0; i < TEST_ARRAY_SIZE; i++) {
requests[i].padata.parallel = parallel;
requests[i].padata.serial = serial;
requests[i].seq = i;
init_completion(&requests[i].done);
}
for (int i = 0; i < TEST_ARRAY_SIZE; i++) {
padata_do_parallel(ps, &requests[i].padata);
}
// only wait for the last one
// if they were not done serially
// the serial_cnt will not be TEST_ARRAY_SIZE
// there was a shuffering
int last = TEST_ARRAY_SIZE - 1;
wait_for_completion(&requests[last].done);
if (serial_cnt != TEST_ARRAY_SIZE)
shuffled = 1;
printk(KERN_INFO "padata_test: shuffled %d serial_cnt %d\n", shuffled,
serial_cnt);
return 0;
}
static void __exit padata_test_exit(void) {
padata_free_shell(ps);
padata_free(pinst);
}
module_init(padata_test_init);
module_exit(padata_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wangjinchao");
MODULE_DESCRIPTION("padata Test Module");
```Makefile
---------
```makefile obj-m += padata_test.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ```
run.sh
--------
```bash make dmesg -C insmod padata_test.ko rmmod padata_test dmesg|grep serial_cnt ```
Steffen Klassert
maintainerHi,
Quoted 30 lines · Wang Jinchao
This is a refactored version with the following main changes:
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
- Removal of CPU-related logic, sysfs-related interfaces
- removal of structures likepadata_cpumask, and deletion ofparallel_data
- Using completion to maintain sequencing
- no longer using lists
- removing structures likepadata_listandpadata_serial_queue
- Removal ofpadata_do_serial()
- padata automatically ensures the calling sequence.Testing was conducted using ltp's
pcrypt_aead01, and the execution time comparison between the old and new versions is as follows:Old Version:
real 0m27.451s
user 0m0.031s
sys 0m0.260sNew Version:
real 0m21.351s
user 0m0.023s
sys 0m0.260sSigned-off-by Wang Jinchao <[email protected]>--- crypto/pcrypt.c | 34 +- include/linux/padata.h | 95 +---- kernel/padata.c | 815 ++--------------------------------------- 3 files changed, 43 insertions(+), 901 deletions(-)
...
crypto/pcrypt.c static int pcrypt_create(struct crypto_template *tmpl, struct rtattr **tb) · line 317
Quoted 12 lines
crypto/pcrypt.c +0
-11-static int pcrypt_sysfs_add (struct padata_instance *pinst,const char *name) -{ -int ret; - - pinst->kobj.kset = pcrypt_kset; - ret =kobject_add (&pinst->kobj,NULL ,"%s" , name); -if (!ret) -kobject_uevent (&pinst->kobj,KOBJ_ADD ); - -return ret; -}
Users might rely on the existence of that sysfs files, so removing this might be dangerous.
kernel/padata.c static void padata_parallel_worker(struct work_struct *parallel_work) · line 360
Quoted 8 lines
static void
padata_serial_worker(struct work_struct *serial_work){kernel/padata.c +0
-6-struct padata_serial_queue *squeue; -struct parallel_data *pd; -LIST_HEAD (local_list); -int cnt; - -local_bh_disable ();
Note that the networking RX path must run with BHs off. The call to padata_do_parallel might come with BHs off and the serialization callback should also called with BHs off.
Please make sure that the networking usecase continues to work with that refactorization.
Thanks!
Daniel Jordan
maintainerHello,
Quoted 1 line · Wang Jinchao
This is a refactored version with the following main changes:
The RFC overall is a nice simplification, and the basic approach of using an ordered workqueue seems to work.
Quoted 1 line
- The parallel workqueue no longer uses the
WQ_UNBOUNDattribute
What's the justification here? If it improves performance, please show numbers. Earlier tests[0] showed a large improvement when adding this flag.
[0] https://lore.kernel.org/linux-crypto/[email protected]/
Quoted 1 line
- Removal of CPU-related logic, sysfs-related interfaces
I agree with Steffen that we should continue to honor the cpumasks that the user sets.
The simplest way I see to make the parallel mask work with your refactor is to just make the parallel workqueue unbound again, since setting workqueue attributes is only allowed for unbound, and bring back some of the plumbing that leads to the apply_workqueue_attrs call.
The serial mask is trickier. Changing attributes of an ordered workqueue (the cpumask in this case) makes the kernel throw a warning...
static int apply_workqueue_attrs_locked
...
/* creating multiple pwqs breaks ordering guarantee */
if (!list_empty(&wq->pwqs)) {
if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
return -EINVAL;
wq->flags &= ~__WQ_ORDERED;
}...but I'm not sure this is a fundamental limitation. The changelog of 0a94efb5acbb ("workqueue: implicit ordered attribute should be overridable") says changes to "max_active and some attribute changes" are rejected, but it might be possible to relax the warning to allow setting a cpumask while still rejecting other changes.
Quoted 8 lines
Testing was conducted using ltp's
pcrypt_aead01, and the execution time comparison between the old and new versions is as follows:Old Version:
real 0m27.451s
user 0m0.031s
sys 0m0.260s
Quoted 4 lines
New Version:
real 0m21.351s
user 0m0.023s
sys 0m0.260s
Great speedup. A test that runs many requests for a long time in parallel is also good to run, such as [0].
Quoted 1 line
(quoted diff) +0
-0@@ -986,57 +281,27 @@ struct padata_instance *padata_alloc(const char *name)
...
kernel/padata.c struct padata_instance *padata_alloc(const char *name) · line 292
Quoted 3 lines
kernel/padata.c +3
-0+ pinst->serial_wq =alloc_ordered_workqueue ("%s_serial" , +WQ_MEM_RECLAIM |WQ_FREEZABLE , + name);
Why add these two WQ_ flags? Also, whitespace is kinda funky.
Quoted 8 lines · Daniel Jordan
Hello,
Quoted 1 line · Wang Jinchao
This is a refactored version with the following main changes:
The RFC overall is a nice simplification, and the basic approach of using an ordered workqueue seems to work.
Quoted 8 lines
Quoted 1 line
- The parallel workqueue no longer uses the
WQ_UNBOUNDattributeWhat's the justification here? If it improves performance, please show numbers. Earlier tests[0] showed a large improvement when adding this flag.
When I wrote the email on September 28th, I only used the "pcrypt_aead01" test case from LTP. Thank you for you and Steffen's responses. I now have more test cases, but I haven't tested them yet.
Quoted 9 lines
Quoted 1 line
- Removal of CPU-related logic, sysfs-related interfaces
I agree with Steffen that we should continue to honor the cpumasks that the user sets.
The simplest way I see to make the parallel mask work with your refactor is to just make the parallel workqueue unbound again, since setting workqueue attributes is only allowed for unbound, and bring back some of the plumbing that leads to the
apply_workqueue_attrscall.
You've convinced me, and I agree with your stance on keeping the cpumask. So, using WQ_UNBOUND is the right choice, and this will be reflected in my upcoming patches.
Quoted 14 lines
The serial mask is trickier. Changing attributes of an ordered workqueue (the cpumask in this case) makes the kernel throw a warning...
static int
apply_workqueue_attrs_locked... /* creating multiple pwqs breaks ordering guarantee */ if (!list_empty(&wq->pwqs)) { if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT)) return -EINVAL; wq->flags &= ~__WQ_ORDERED; }
Quoted 5 lines
...but I'm not sure this is a fundamental limitation. The changelog of
0a94efb5acbb("workqueue: implicit ordered attribute should be overridable") says changes to "max_activeand some attribute changes" are rejected, but it might be possible to relax the warning to allow setting a cpumask while still rejecting other changes.
Workqueue provides the alloc_ordered_workqueue method, which may be more suitable for serial workers.
Quoted 9 lines
Quoted 9 lines
Testing was conducted using ltp's
pcrypt_aead01, and the execution time comparison between the old and new versions is as follows:Old Version:
real 0m27.451s
user 0m0.031s
sys 0m0.260s
Quoted 8 lines
Quoted 4 lines
New Version:
real 0m21.351s
user 0m0.023s
sys 0m0.260sGreat speedup. A test that runs many requests for a long time in parallel is also good to run, such as [0].
I will conduct the test as previously mentioned.
Quoted 7 lines
Quoted 1 line
(quoted diff) +0
-0@@ -986,57 +281,27 @@ struct padata_instance *padata_alloc(const char *name)...
kernel/padata.c struct padata_instance *padata_alloc(const char *name) · line 292
Quoted 3 lines
kernel/padata.c +3
-0+ pinst->serial_wq =alloc_ordered_workqueue ("%s_serial" , +WQ_MEM_RECLAIM |WQ_FREEZABLE , + name);Why add these two
WQ_flags? Also, whitespace is kinda funky.
You're right, I need to adjust this part of the code.
Daniel Jordan
maintainerQuoted 17 lines · Wang Jinchao
include/linux/padata.h +0
-17-/** -* struct parallel_data - Internal control structure, covers everything -* that depends on the cpumask in use. -* -* @ps: padata_shell object. -* @reorder_list: percpu reorder lists -* @squeue: percpu padata queues used for serialuzation. -* @refcnt: Number of objects holding a reference on this parallel_data. -* @seq_nr: Sequence number of the parallelized data object. -* @processed: Number of already processed objects. -* @cpu: Next CPU to be processed. -* @cpumask: The cpumasks in use for parallel and serial workers. -* @reorder_work: work struct for reordering. -* @lock: Reorder lock. -*/ -struct parallel_data { -struct padata_shell *ps;
include/linux/padata.h line 107
Quoted 10 lines
include/linux/padata.h +0
-10-struct padata_list __percpu *reorder_list; -struct padata_serial_queue __percpu *squeue; -refcount_t refcnt; -unsigned int seq_nr; -unsigned int processed; -int cpu; -struct padata_cpumask cpumask; -struct work_struct reorder_work; -spinlock_t ____cacheline_aligned lock; -};
reorder_list used to serialize one sequence of objects per padata_shell, but now serial_wq serializes all sequences of objects in one list of work_structs. That works in theory, since a total order can maintain each sequence's order, but it's possible (not sure yet, need to think more) that this could lead to deadlocks or other issues in odd cases such as the one that padata_shell was introduced for in bbefa1dd6a6d ("crypto: pcrypt - Avoid deadlock by using per-instance padata queues").
The reproducer in that commit produces this splat when testing the RFC. Not sure if it's related to the above though.
[ 40.084146] alg: aead: pcrypt(pcrypt(rfc4106-gcm-aesni)) encryption test failed (wrong result) on test vector 1, cfg="in-place (one sglist)" [ 40.087192] alg: self-tests for rfc4106(gcm(aes)) using pcrypt(pcrypt(rfc4106-gcm-aesni)) failed (rc=-22) [ 40.087195] ------------[ cut here ]------------ [ 40.090296] alg: self-tests for rfc4106(gcm(aes)) using pcrypt(pcrypt(rfc4106-gcm-aesni)) failed (rc=-22) [ 40.090313] WARNING: CPU: 4 PID: 321 at crypto/testmgr.c:5936 alg_test+0x404/0x510 [ 40.094020] Modules linked in: pcrypt [ 40.094882] CPU: 4 PID: 321 Comm: cryptomgr_test Not tainted 6.6.0-rc6-padata-refact-rfc-v1-test+ #3 [ 40.096856] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-2-2 04/01/2014 [ 40.098838] RIP: 0010:alg_test+0x404/0x510 [ 40.099664] Code: e9 4a fd ff ff c6 44 24 17 01 41 bd ff ff ff ff e9 d1 fc ff ff 44 89 e9 48 89 da 4c 89 e6 48 c7 c7 a0 59 1d 82 e8 1c 45 c4 ff <0f> 0b e9 aa fe ff ff 0f 0b 48 c7 c7 80 58 1d 82 e8 e7 c6 cc ff e9 [ 40.103180] RSP: 0018:ffffc90000343e10 EFLAGS: 00010286 [ 40.104322] RAX: 0000000000000000 RBX: ffff88800421cc00 RCX: 0000000000000000 [ 40.105875] RDX: 0000000000000002 RSI: ffffc90000343cc0 RDI: 00000000ffffffff [ 40.107467] RBP: 0000000000000883 R08: 00000000ffffdfff R09: 0000000000000001 [ 40.109249] R10: 00000000ffffdfff R11: ffffffff824722a0 R12: ffff88800421cc80 [ 40.110862] R13: 00000000ffffffea R14: 00000000ffffffff R15: 0000000000000000 [ 40.112354] FS: 0000000000000000(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000 [ 40.114132] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 40.115130] CR2: 00007f1808faba38 CR3: 000000000243e002 CR4: 0000000000170ea0 [ 40.115959] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 40.116630] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 40.117261] Call Trace: [ 40.117559] <TASK> [ 40.117811] ? __warn+0x7d/0x140 [ 40.118165] ? alg_test+0x404/0x510 [ 40.118452] ? report_bug+0x18d/0x1c0 [ 40.118743] ? handle_bug+0x3a/0x70 [ 40.118998] ? exc_invalid_op+0x13/0x60 [ 40.119265] ? asm_exc_invalid_op+0x16/0x20 [ 40.119597] ? alg_test+0x404/0x510 [ 40.119918] ? _raw_spin_unlock_irqrestore+0x1b/0x40 [ 40.120390] ? try_to_wake_up+0x9a/0x6a0 [ 40.120749] ? preempt_count_add+0x6a/0xa0 [ 40.121121] ? __pfx_cryptomgr_test+0x10/0x10 [ 40.121494] cryptomgr_test+0x20/0x40 [ 40.121751] kthread+0x100/0x130 [ 40.121979] ? __pfx_kthread+0x10/0x10 [ 40.122247] ret_from_fork+0x30/0x50 [ 40.122511] ? __pfx_kthread+0x10/0x10 [ 40.122775] ret_from_fork_asm+0x1b/0x30 [ 40.123050] </TASK> [ 40.123207] ---[ end trace 0000000000000000 ]---
Quoted 29 lines · Daniel Jordan
Quoted 17 lines · Wang Jinchao
include/linux/padata.h +0
-17-/** -* struct parallel_data - Internal control structure, covers everything -* that depends on the cpumask in use. -* -* @ps: padata_shell object. -* @reorder_list: percpu reorder lists -* @squeue: percpu padata queues used for serialuzation. -* @refcnt: Number of objects holding a reference on this parallel_data. -* @seq_nr: Sequence number of the parallelized data object. -* @processed: Number of already processed objects. -* @cpu: Next CPU to be processed. -* @cpumask: The cpumasks in use for parallel and serial workers. -* @reorder_work: work struct for reordering. -* @lock: Reorder lock. -*/ -struct parallel_data { -struct padata_shell *ps;include/linux/padata.h line 107
Quoted 10 lines
include/linux/padata.h +0
-10-struct padata_list __percpu *reorder_list; -struct padata_serial_queue __percpu *squeue; -refcount_t refcnt; -unsigned int seq_nr; -unsigned int processed; -int cpu; -struct padata_cpumask cpumask; -struct work_struct reorder_work; -spinlock_t ____cacheline_aligned lock; -};
Quoted 8 lines
reorder_listused to serialize one sequence of objects perpadata_shell, but nowserial_wqserializes all sequences of objects in one list ofwork_structs. That works in theory, since a total order can maintain each sequence's order, but it's possible (not sure yet, need to think more) that this could lead to deadlocks or other issues in odd cases such as the one thatpadata_shellwas introduced for inbbefa1dd6a6d("crypto: pcrypt - Avoid deadlock by using per-instance padata queues").
Yes, you are correct. This version is not only ordered at the padata_shell level but at the instance level, which indeed doesn't align with the design. Apart from potential deadlocks, it may also cause a padata_shell_B that should have completed earlier to be blocked by an unrelated padata_shell_B. I will address this issue in subsequent patches.
Quoted 38 lines · Wang Jinchao
Quoted 29 lines · Daniel Jordan
Quoted 17 lines · Wang Jinchao
include/linux/padata.h +0
-17-/** -* struct parallel_data - Internal control structure, covers everything -* that depends on the cpumask in use. -* -* @ps: padata_shell object. -* @reorder_list: percpu reorder lists -* @squeue: percpu padata queues used for serialuzation. -* @refcnt: Number of objects holding a reference on this parallel_data. -* @seq_nr: Sequence number of the parallelized data object. -* @processed: Number of already processed objects. -* @cpu: Next CPU to be processed. -* @cpumask: The cpumasks in use for parallel and serial workers. -* @reorder_work: work struct for reordering. -* @lock: Reorder lock. -*/ -struct parallel_data { -struct padata_shell *ps;include/linux/padata.h line 107
Quoted 10 lines
include/linux/padata.h +0
-10-struct padata_list __percpu *reorder_list; -struct padata_serial_queue __percpu *squeue; -refcount_t refcnt; -unsigned int seq_nr; -unsigned int processed; -int cpu; -struct padata_cpumask cpumask; -struct work_struct reorder_work; -spinlock_t ____cacheline_aligned lock; -};Quoted 8 lines
reorder_listused to serialize one sequence of objects perpadata_shell, but nowserial_wqserializes all sequences of objects in one list ofwork_structs. That works in theory, since a total order can maintain each sequence's order, but it's possible (not sure yet, need to think more) that this could lead to deadlocks or other issues in odd cases such as the one thatpadata_shellwas introduced for inbbefa1dd6a6d("crypto: pcrypt - Avoid deadlock by using per-instance padata queues").
Quoted 5 lines
Yes, you are correct. This version is not only ordered at the
padata_shelllevel but at the instance level, which indeed doesn't align with the design. Apart from potential deadlocks, it may also cause apadata_shell_Bthat should have completed earlier to be blocked by an unrelatedpadata_shell_B. I will address this issue in subsequent patches.
Apart from potential deadlocks, it may also cause a padata_shell_B that should have completed earlier to be blocked by an unrelated padata_shell_A. I will address this issue in subsequent patches.