]>
git.proxmox.com Git - mirror_spl.git/blob - src/splat/splat-taskq.c
614e7136c37af2a876730d2ae86c9b347ecc7710
1 #include <sys/zfs_context.h>
2 #include <sys/splat-ctl.h>
4 #define KZT_SUBSYSTEM_TASKQ 0x0200
5 #define KZT_TASKQ_NAME "taskq"
6 #define KZT_TASKQ_DESC "Kernel Task Queue Tests"
8 #define KZT_TASKQ_TEST1_ID 0x0201
9 #define KZT_TASKQ_TEST1_NAME "single"
10 #define KZT_TASKQ_TEST1_DESC "Single task queue, single task"
12 #define KZT_TASKQ_TEST2_ID 0x0202
13 #define KZT_TASKQ_TEST2_NAME "multiple"
14 #define KZT_TASKQ_TEST2_DESC "Multiple task queues, multiple tasks"
16 typedef struct kzt_taskq_arg
{
23 /* Validation Test 1 - Create a taskq, queue a task, wait until
24 * task completes, ensure task ran properly, cleanup taskq,
27 kzt_taskq_test1_func(void *arg
)
29 kzt_taskq_arg_t
*tq_arg
= (kzt_taskq_arg_t
*)arg
;
32 kzt_vprint(tq_arg
->file
, KZT_TASKQ_TEST1_NAME
,
33 "Taskq '%s' function '%s' setting flag\n",
34 tq_arg
->name
, sym2str(kzt_taskq_test1_func
));
39 kzt_taskq_test1(struct file
*file
, void *arg
)
43 kzt_taskq_arg_t tq_arg
;
45 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
, "Taskq '%s' creating\n",
46 KZT_TASKQ_TEST1_NAME
);
47 if ((tq
= taskq_create(KZT_TASKQ_TEST1_NAME
, 1, 0, 0, 0, 0)) == NULL
) {
48 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
,
49 "Taskq '%s' create failed\n",
50 KZT_TASKQ_TEST1_NAME
);
57 tq_arg
.name
= KZT_TASKQ_TEST1_NAME
;
59 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
,
60 "Taskq '%s' function '%s' dispatching\n",
61 tq_arg
.name
, sym2str(kzt_taskq_test1_func
));
62 if ((id
= taskq_dispatch(tq
, kzt_taskq_test1_func
, &tq_arg
, 0)) == 0) {
63 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
,
64 "Taskq '%s' function '%s' dispatch failed\n",
65 tq_arg
.name
, sym2str(kzt_taskq_test1_func
));
70 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
, "Taskq '%s' waiting\n",
73 kzt_vprint(file
, KZT_TASKQ_TEST1_NAME
, "Taskq '%s' destroying\n",
77 return (tq_arg
.flag
) ? 0 : -EINVAL
;
80 /* Validation Test 2 - Create multiple taskq's, each with multiple tasks,
81 * wait until all tasks complete, ensure all tasks ran properly and in the
82 * the correct order, cleanup taskq's
85 kzt_taskq_test2_func1(void *arg
)
87 kzt_taskq_arg_t
*tq_arg
= (kzt_taskq_arg_t
*)arg
;
90 kzt_vprint(tq_arg
->file
, KZT_TASKQ_TEST2_NAME
,
91 "Taskq '%s/%d' function '%s' flag = %d = %d * 2\n",
92 tq_arg
->name
, tq_arg
->id
,
93 sym2str(kzt_taskq_test2_func1
),
94 tq_arg
->flag
* 2, tq_arg
->flag
);
99 kzt_taskq_test2_func2(void *arg
)
101 kzt_taskq_arg_t
*tq_arg
= (kzt_taskq_arg_t
*)arg
;
104 kzt_vprint(tq_arg
->file
, KZT_TASKQ_TEST2_NAME
,
105 "Taskq '%s/%d' function '%s' flag = %d = %d + 1\n",
106 tq_arg
->name
, tq_arg
->id
,
107 sym2str(kzt_taskq_test2_func2
),
108 tq_arg
->flag
+ 1, tq_arg
->flag
);
112 #define TEST2_TASKQS 8
114 kzt_taskq_test2(struct file
*file
, void *arg
) {
115 taskq_t
*tq
[TEST2_TASKQS
] = { NULL
};
117 kzt_taskq_arg_t tq_args
[TEST2_TASKQS
];
120 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
122 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
, "Taskq '%s/%d' "
123 "creating\n", KZT_TASKQ_TEST2_NAME
, i
);
124 if ((tq
[i
] = taskq_create(KZT_TASKQ_TEST2_NAME
,
125 1, 0, 0, 0, 0)) == NULL
) {
126 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
127 "Taskq '%s/%d' create failed\n",
128 KZT_TASKQ_TEST2_NAME
, i
);
135 tq_args
[i
].file
= file
;
136 tq_args
[i
].name
= KZT_TASKQ_TEST2_NAME
;
138 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
139 "Taskq '%s/%d' function '%s' dispatching\n",
140 tq_args
[i
].name
, tq_args
[i
].id
,
141 sym2str(kzt_taskq_test2_func1
));
142 if ((id
= taskq_dispatch(
143 tq
[i
], kzt_taskq_test2_func1
, &tq_args
[i
], 0)) == 0) {
144 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
145 "Taskq '%s/%d' function '%s' dispatch "
146 "failed\n", tq_args
[i
].name
, tq_args
[i
].id
,
147 sym2str(kzt_taskq_test2_func1
));
152 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
153 "Taskq '%s/%d' function '%s' dispatching\n",
154 tq_args
[i
].name
, tq_args
[i
].id
,
155 sym2str(kzt_taskq_test2_func2
));
156 if ((id
= taskq_dispatch(
157 tq
[i
], kzt_taskq_test2_func2
, &tq_args
[i
], 0)) == 0) {
158 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
159 "Taskq '%s/%d' function '%s' dispatch failed\n",
160 tq_args
[i
].name
, tq_args
[i
].id
,
161 sym2str(kzt_taskq_test2_func2
));
167 /* When rc is set we're effectively just doing cleanup here, so
168 * ignore new errors in that case. They just cause noise. */
169 for (i
= 0; i
< TEST2_TASKQS
; i
++) {
171 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
172 "Taskq '%s/%d' waiting\n",
173 tq_args
[i
].name
, tq_args
[i
].id
);
175 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
176 "Taskq '%s/%d; destroying\n",
177 tq_args
[i
].name
, tq_args
[i
].id
);
178 taskq_destory(tq
[i
]);
180 if (!rc
&& tq_args
[i
].flag
!= ((i
* 2) + 1)) {
181 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
182 "Taskq '%s/%d' processed tasks "
183 "out of order; %d != %d\n",
184 tq_args
[i
].name
, tq_args
[i
].id
,
185 tq_args
[i
].flag
, i
* 2 + 1);
188 kzt_vprint(file
, KZT_TASKQ_TEST2_NAME
,
189 "Taskq '%s/%d' processed tasks "
190 "in the correct order; %d == %d\n",
191 tq_args
[i
].name
, tq_args
[i
].id
,
192 tq_args
[i
].flag
, i
* 2 + 1);
203 kzt_subsystem_t
*sub
;
205 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
209 memset(sub
, 0, sizeof(*sub
));
210 strncpy(sub
->desc
.name
, KZT_TASKQ_NAME
, KZT_NAME_SIZE
);
211 strncpy(sub
->desc
.desc
, KZT_TASKQ_DESC
, KZT_DESC_SIZE
);
212 INIT_LIST_HEAD(&sub
->subsystem_list
);
213 INIT_LIST_HEAD(&sub
->test_list
);
214 spin_lock_init(&sub
->test_lock
);
215 sub
->desc
.id
= KZT_SUBSYSTEM_TASKQ
;
217 KZT_TEST_INIT(sub
, KZT_TASKQ_TEST1_NAME
, KZT_TASKQ_TEST1_DESC
,
218 KZT_TASKQ_TEST1_ID
, kzt_taskq_test1
);
219 KZT_TEST_INIT(sub
, KZT_TASKQ_TEST2_NAME
, KZT_TASKQ_TEST2_DESC
,
220 KZT_TASKQ_TEST2_ID
, kzt_taskq_test2
);
226 kzt_taskq_fini(kzt_subsystem_t
*sub
)
229 KZT_TEST_FINI(sub
, KZT_TASKQ_TEST2_ID
);
230 KZT_TEST_FINI(sub
, KZT_TASKQ_TEST1_ID
);
237 return KZT_SUBSYSTEM_TASKQ
;