1dnl #
2dnl # 2.6.36 API change,
3dnl # REQ_FAILFAST_{DEV|TRANSPORT|DRIVER}
4dnl # REQ_DISCARD
5dnl # REQ_FLUSH
6dnl #
7dnl # 4.8 - 4.9 API,
8dnl # REQ_FLUSH was renamed to REQ_PREFLUSH
9dnl #
10AC_DEFUN([ZFS_AC_KERNEL_SRC_REQ], [
11	ZFS_LINUX_TEST_SRC([req_failfast_mask], [
12		#include <linux/bio.h>
13	],[
14		int flags __attribute__ ((unused));
15		flags = REQ_FAILFAST_MASK;
16	])
17
18	ZFS_LINUX_TEST_SRC([req_discard], [
19		#include <linux/bio.h>
20	],[
21		int flags __attribute__ ((unused));
22		flags = REQ_DISCARD;
23	])
24
25	ZFS_LINUX_TEST_SRC([req_flush], [
26		#include <linux/bio.h>
27	],[
28		int flags __attribute__ ((unused));
29		flags = REQ_FLUSH;
30	])
31
32	ZFS_LINUX_TEST_SRC([req_preflush], [
33		#include <linux/bio.h>
34	],[
35		int flags __attribute__ ((unused));
36		flags = REQ_PREFLUSH;
37	])
38])
39
40AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_FAILFAST_MASK], [
41	AC_MSG_CHECKING([whether REQ_FAILFAST_MASK is defined])
42	ZFS_LINUX_TEST_RESULT([req_failfast_mask], [
43		AC_MSG_RESULT(yes)
44	],[
45		ZFS_LINUX_TEST_ERROR([REQ_FAILFAST_MASK])
46	])
47])
48
49AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_DISCARD], [
50	AC_MSG_CHECKING([whether REQ_DISCARD is defined])
51	ZFS_LINUX_TEST_RESULT([req_discard], [
52		AC_MSG_RESULT(yes)
53		AC_DEFINE(HAVE_REQ_DISCARD, 1, [REQ_DISCARD is defined])
54	],[
55		AC_MSG_RESULT(no)
56	])
57])
58
59AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_FLUSH], [
60	AC_MSG_CHECKING([whether REQ_FLUSH is defined])
61	ZFS_LINUX_TEST_RESULT([req_flush], [
62		AC_MSG_RESULT(yes)
63		AC_DEFINE(HAVE_REQ_FLUSH, 1, [REQ_FLUSH is defined])
64	],[
65		AC_MSG_RESULT(no)
66	])
67])
68
69AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_PREFLUSH], [
70	AC_MSG_CHECKING([whether REQ_PREFLUSH is defined])
71	ZFS_LINUX_TEST_RESULT([req_preflush], [
72		AC_MSG_RESULT(yes)
73		AC_DEFINE(HAVE_REQ_PREFLUSH, 1, [REQ_PREFLUSH is defined])
74	],[
75		AC_MSG_RESULT(no)
76	])
77])
78
79dnl #
80dnl # Linux 4.8 API,
81dnl #
82dnl # The bio_op() helper was introduced as a replacement for explicitly
83dnl # checking the bio->bi_rw flags.  The following checks are used to
84dnl # detect if a specific operation is supported.
85dnl #
86AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_OPS], [
87	ZFS_LINUX_TEST_SRC([req_op_discard], [
88		#include <linux/blk_types.h>
89	],[
90		int op __attribute__ ((unused)) = REQ_OP_DISCARD;
91	])
92
93	ZFS_LINUX_TEST_SRC([req_op_secure_erase], [
94		#include <linux/blk_types.h>
95	],[
96		int op __attribute__ ((unused)) = REQ_OP_SECURE_ERASE;
97	])
98
99	ZFS_LINUX_TEST_SRC([req_op_flush], [
100		#include <linux/blk_types.h>
101	],[
102		int op __attribute__ ((unused)) = REQ_OP_FLUSH;
103	])
104
105	ZFS_LINUX_TEST_SRC([bio_bi_opf], [
106		#include <linux/bio.h>
107	],[
108		struct bio bio __attribute__ ((unused));
109		bio.bi_opf = 0;
110	])
111
112	ZFS_LINUX_TEST_SRC([bio_set_op_attrs], [
113		#include <linux/bio.h>
114	],[
115		struct bio *bio __attribute__ ((unused)) = NULL;
116		bio_set_op_attrs(bio, 0, 0);
117	])
118])
119
120AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_OP_DISCARD], [
121	AC_MSG_CHECKING([whether REQ_OP_DISCARD is defined])
122	ZFS_LINUX_TEST_RESULT([req_op_discard], [
123		AC_MSG_RESULT(yes)
124		AC_DEFINE(HAVE_REQ_OP_DISCARD, 1, [REQ_OP_DISCARD is defined])
125	],[
126		AC_MSG_RESULT(no)
127	])
128])
129
130AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_OP_SECURE_ERASE], [
131	AC_MSG_CHECKING([whether REQ_OP_SECURE_ERASE is defined])
132	ZFS_LINUX_TEST_RESULT([req_op_secure_erase], [
133		AC_MSG_RESULT(yes)
134		AC_DEFINE(HAVE_REQ_OP_SECURE_ERASE, 1,
135		    [REQ_OP_SECURE_ERASE is defined])
136	],[
137		AC_MSG_RESULT(no)
138	])
139])
140
141AC_DEFUN([ZFS_AC_KERNEL_BIO_REQ_OP_FLUSH], [
142	AC_MSG_CHECKING([whether REQ_OP_FLUSH is defined])
143	ZFS_LINUX_TEST_RESULT([req_op_flush], [
144		AC_MSG_RESULT(yes)
145		AC_DEFINE(HAVE_REQ_OP_FLUSH, 1, [REQ_OP_FLUSH is defined])
146	],[
147		AC_MSG_RESULT(no)
148	])
149])
150
151AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_OPF], [
152	AC_MSG_CHECKING([whether bio->bi_opf is defined])
153	ZFS_LINUX_TEST_RESULT([bio_bi_opf], [
154		AC_MSG_RESULT(yes)
155		AC_DEFINE(HAVE_BIO_BI_OPF, 1, [bio->bi_opf is defined])
156	],[
157		AC_MSG_RESULT(no)
158	])
159])
160
161AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_OP_ATTRS], [
162	AC_MSG_CHECKING([whether bio_set_op_attrs is available])
163	ZFS_LINUX_TEST_RESULT([bio_set_op_attrs], [
164		AC_MSG_RESULT(yes)
165		AC_DEFINE(HAVE_BIO_SET_OP_ATTRS, 1,
166		    [bio_set_op_attrs is available])
167	],[
168		AC_MSG_RESULT(no)
169	])
170])
171
172dnl #
173dnl # Linux 4.14 API,
174dnl #
175dnl # The bio_set_dev() helper macro was introduced as part of the transition
176dnl # to have struct gendisk in struct bio.
177dnl #
178dnl # Linux 5.0 API,
179dnl #
180dnl # The bio_set_dev() helper macro was updated to internally depend on
181dnl # bio_associate_blkg() symbol which is exported GPL-only.
182dnl #
183AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV], [
184	ZFS_LINUX_TEST_SRC([bio_set_dev], [
185		#include <linux/bio.h>
186		#include <linux/fs.h>
187	],[
188		struct block_device *bdev = NULL;
189		struct bio *bio = NULL;
190		bio_set_dev(bio, bdev);
191	], [], [ZFS_META_LICENSE])
192])
193
194dnl #
195dnl # Linux 5.16 API
196dnl #
197dnl # bio_set_dev is no longer a helper macro and is now an inline function,
198dnl # meaning that the function it calls internally can no longer be overridden
199dnl # by our code
200dnl #
201AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO], [
202	ZFS_LINUX_TEST_SRC([bio_set_dev_macro], [
203		#include <linux/bio.h>
204		#include <linux/fs.h>
205	],[
206		#ifndef bio_set_dev
207		#error Not a macro
208		#endif
209	], [], [ZFS_META_LICENSE])
210])
211
212AC_DEFUN([ZFS_AC_KERNEL_BIO_SET_DEV], [
213	AC_MSG_CHECKING([whether bio_set_dev() is available])
214	ZFS_LINUX_TEST_RESULT([bio_set_dev], [
215		AC_MSG_RESULT(yes)
216		AC_DEFINE(HAVE_BIO_SET_DEV, 1, [bio_set_dev() is available])
217
218		AC_MSG_CHECKING([whether bio_set_dev() is GPL-only])
219		ZFS_LINUX_TEST_RESULT([bio_set_dev_license], [
220			AC_MSG_RESULT(no)
221		],[
222			AC_MSG_RESULT(yes)
223			AC_DEFINE(HAVE_BIO_SET_DEV_GPL_ONLY, 1,
224			    [bio_set_dev() GPL-only])
225		])
226
227		AC_MSG_CHECKING([whether bio_set_dev() is a macro])
228		ZFS_LINUX_TEST_RESULT([bio_set_dev_macro], [
229			AC_MSG_RESULT(yes)
230			AC_DEFINE(HAVE_BIO_SET_DEV_MACRO, 1,
231			    [bio_set_dev() is a macro])
232		],[
233			AC_MSG_RESULT(no)
234		])
235	],[
236		AC_MSG_RESULT(no)
237	])
238])
239
240dnl #
241dnl # 4.3 API change
242dnl # Error argument dropped from bio_endio in favor of newly introduced
243dnl # bio->bi_error. This also replaces bio->bi_flags value BIO_UPTODATE.
244dnl # Introduced by torvalds/linux@4246a0b63bd8f56a1469b12eafeb875b1041a451
245dnl # ("block: add a bi_error field to struct bio").
246dnl #
247AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS], [
248	ZFS_LINUX_TEST_SRC([bio_end_io_t_args], [
249		#include <linux/bio.h>
250		void wanted_end_io(struct bio *bio) { return; }
251		bio_end_io_t *end_io __attribute__ ((unused)) = wanted_end_io;
252	], [])
253])
254
255AC_DEFUN([ZFS_AC_KERNEL_BIO_END_IO_T_ARGS], [
256	AC_MSG_CHECKING([whether bio_end_io_t wants 1 arg])
257	ZFS_LINUX_TEST_RESULT([bio_end_io_t_args], [
258		AC_MSG_RESULT(yes)
259		AC_DEFINE(HAVE_1ARG_BIO_END_IO_T, 1,
260		    [bio_end_io_t wants 1 arg])
261	], [
262		AC_MSG_RESULT(no)
263	])
264])
265
266dnl #
267dnl # 4.13 API change
268dnl # The bio->bi_error field was replaced with bio->bi_status which is an
269dnl # enum which describes all possible error types.
270dnl #
271AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BI_STATUS], [
272	ZFS_LINUX_TEST_SRC([bio_bi_status], [
273		#include <linux/bio.h>
274	], [
275		struct bio bio __attribute__ ((unused));
276		blk_status_t status __attribute__ ((unused)) = BLK_STS_OK;
277		bio.bi_status = status;
278	])
279])
280
281AC_DEFUN([ZFS_AC_KERNEL_BIO_BI_STATUS], [
282	AC_MSG_CHECKING([whether bio->bi_status exists])
283	ZFS_LINUX_TEST_RESULT([bio_bi_status], [
284		AC_MSG_RESULT(yes)
285		AC_DEFINE(HAVE_BIO_BI_STATUS, 1, [bio->bi_status exists])
286	],[
287		AC_MSG_RESULT(no)
288	])
289])
290
291dnl #
292dnl # 3.14 API change,
293dnl # Immutable biovecs. A number of fields of struct bio are moved to
294dnl # struct bvec_iter.
295dnl #
296AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER], [
297	ZFS_LINUX_TEST_SRC([bio_bvec_iter], [
298		#include <linux/bio.h>
299	],[
300		struct bio bio;
301		bio.bi_iter.bi_sector = 0;
302	])
303])
304
305AC_DEFUN([ZFS_AC_KERNEL_BIO_BVEC_ITER], [
306	AC_MSG_CHECKING([whether bio has bi_iter])
307	ZFS_LINUX_TEST_RESULT([bio_bvec_iter], [
308		AC_MSG_RESULT(yes)
309		AC_DEFINE(HAVE_BIO_BVEC_ITER, 1, [bio has bi_iter])
310	],[
311		AC_MSG_RESULT(no)
312	])
313])
314
315dnl #
316dnl # 4.8 API change
317dnl # The rw argument has been removed from submit_bio/submit_bio_wait.
318dnl # Callers are now expected to set bio->bi_rw instead of passing it in.
319dnl #
320AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_SUBMIT_BIO], [
321	ZFS_LINUX_TEST_SRC([submit_bio], [
322		#include <linux/bio.h>
323	],[
324		struct bio *bio = NULL;
325		(void) submit_bio(bio);
326	])
327])
328
329AC_DEFUN([ZFS_AC_KERNEL_BIO_SUBMIT_BIO], [
330	AC_MSG_CHECKING([whether submit_bio() wants 1 arg])
331	ZFS_LINUX_TEST_RESULT([submit_bio], [
332		AC_MSG_RESULT(yes)
333		AC_DEFINE(HAVE_1ARG_SUBMIT_BIO, 1, [submit_bio() wants 1 arg])
334	],[
335		AC_MSG_RESULT(no)
336	])
337])
338
339dnl #
340dnl # 2.6.34 API change
341dnl # current->bio_list
342dnl #
343AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_CURRENT_BIO_LIST], [
344	ZFS_LINUX_TEST_SRC([current_bio_list], [
345		#include <linux/sched.h>
346	], [
347		current->bio_list = (struct bio_list *) NULL;
348	])
349])
350
351AC_DEFUN([ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST], [
352	AC_MSG_CHECKING([whether current->bio_list exists])
353	ZFS_LINUX_TEST_RESULT([current_bio_list], [
354		AC_MSG_RESULT(yes)
355	],[
356		ZFS_LINUX_TEST_ERROR([bio_list])
357	])
358])
359
360dnl #
361dnl # Linux 5.5 API,
362dnl #
363dnl # The Linux 5.5 kernel updated percpu_ref_tryget() which is inlined by
364dnl # blkg_tryget() to use rcu_read_lock() instead of rcu_read_lock_sched().
365dnl # As a side effect the function was converted to GPL-only.
366dnl #
367AC_DEFUN([ZFS_AC_KERNEL_SRC_BLKG_TRYGET], [
368	ZFS_LINUX_TEST_SRC([blkg_tryget], [
369		#include <linux/blk-cgroup.h>
370		#include <linux/bio.h>
371		#include <linux/fs.h>
372	],[
373		struct blkcg_gq blkg __attribute__ ((unused)) = {};
374		bool rc __attribute__ ((unused));
375		rc = blkg_tryget(&blkg);
376	], [], [ZFS_META_LICENSE])
377])
378
379AC_DEFUN([ZFS_AC_KERNEL_BLKG_TRYGET], [
380	AC_MSG_CHECKING([whether blkg_tryget() is available])
381	ZFS_LINUX_TEST_RESULT([blkg_tryget], [
382		AC_MSG_RESULT(yes)
383		AC_DEFINE(HAVE_BLKG_TRYGET, 1, [blkg_tryget() is available])
384
385		AC_MSG_CHECKING([whether blkg_tryget() is GPL-only])
386		ZFS_LINUX_TEST_RESULT([blkg_tryget_license], [
387			AC_MSG_RESULT(no)
388		],[
389			AC_MSG_RESULT(yes)
390			AC_DEFINE(HAVE_BLKG_TRYGET_GPL_ONLY, 1,
391			    [blkg_tryget() GPL-only])
392		])
393	],[
394		AC_MSG_RESULT(no)
395	])
396])
397
398dnl #
399dnl # Linux 5.12 API,
400dnl #
401dnl # The Linux 5.12 kernel updated struct bio to create a new bi_bdev member
402dnl # and bio->bi_disk was moved to bio->bi_bdev->bd_disk
403dnl #
404AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_BDEV_DISK], [
405	ZFS_LINUX_TEST_SRC([bio_bdev_disk], [
406		#include <linux/blk_types.h>
407		#include <linux/blkdev.h>
408	],[
409		struct bio *b = NULL;
410		struct gendisk *d = b->bi_bdev->bd_disk;
411		blk_register_queue(d);
412	])
413])
414
415AC_DEFUN([ZFS_AC_KERNEL_BIO_BDEV_DISK], [
416	AC_MSG_CHECKING([whether bio->bi_bdev->bd_disk exists])
417	ZFS_LINUX_TEST_RESULT([bio_bdev_disk], [
418		AC_MSG_RESULT(yes)
419		AC_DEFINE(HAVE_BIO_BDEV_DISK, 1, [bio->bi_bdev->bd_disk exists])
420	],[
421		AC_MSG_RESULT(no)
422	])
423])
424
425dnl #
426dnl # Linux 5.16 API
427dnl #
428dnl # The Linux 5.16 API for submit_bio changed the return type to be
429dnl # void instead of int
430dnl #
431AC_DEFUN([ZFS_AC_KERNEL_SRC_BDEV_SUBMIT_BIO_RETURNS_VOID], [
432	ZFS_LINUX_TEST_SRC([bio_bdev_submit_bio_void], [
433		#include <linux/blkdev.h>
434	],[
435		struct block_device_operations *bdev = NULL;
436		__attribute__((unused)) void(*f)(struct bio *) = bdev->submit_bio;
437	])
438])
439
440AC_DEFUN([ZFS_AC_KERNEL_BDEV_SUBMIT_BIO_RETURNS_VOID], [
441	AC_MSG_CHECKING(
442		[whether block_device_operations->submit_bio() returns void])
443	ZFS_LINUX_TEST_RESULT([bio_bdev_submit_bio_void], [
444		AC_MSG_RESULT(yes)
445		AC_DEFINE(HAVE_BDEV_SUBMIT_BIO_RETURNS_VOID, 1,
446			[block_device_operations->submit_bio() returns void])
447	],[
448		AC_MSG_RESULT(no)
449	])
450])
451
452dnl #
453dnl # Linux 5.16 API
454dnl #
455dnl # The Linux 5.16 API moved struct blkcg_gq into linux/blk-cgroup.h, which
456dnl # has been around since 2015. This test looks for the presence of that
457dnl # header, so that it can be conditionally included where it exists, but
458dnl # still be backward compatible with kernels that pre-date its introduction.
459dnl #
460AC_DEFUN([ZFS_AC_KERNEL_SRC_BLK_CGROUP_HEADER], [
461	ZFS_LINUX_TEST_SRC([blk_cgroup_header], [
462		#include <linux/blk-cgroup.h>
463	], [])
464])
465
466AC_DEFUN([ZFS_AC_KERNEL_BLK_CGROUP_HEADER], [
467	AC_MSG_CHECKING([whether linux/blk-cgroup.h exists])
468	ZFS_LINUX_TEST_RESULT([blk_cgroup_header],[
469		AC_MSG_RESULT(yes)
470		AC_DEFINE(HAVE_LINUX_BLK_CGROUP_HEADER, 1,
471			[linux/blk-cgroup.h exists])
472	],[
473		AC_MSG_RESULT(no)
474	])
475])
476
477dnl #
478dnl # Linux 5.18 API
479dnl #
480dnl # In 07888c665b405b1cd3577ddebfeb74f4717a84c4 ("block: pass a block_device and opf to bio_alloc")
481dnl #   bio_alloc(gfp_t gfp_mask, unsigned short nr_iovecs)
482dnl # became
483dnl #   bio_alloc(struct block_device *bdev, unsigned short nr_vecs, unsigned int opf, gfp_t gfp_mask)
484dnl # however
485dnl # > NULL/0 can be passed, both for the
486dnl # > passthrough case on a raw request_queue and to temporarily avoid
487dnl # > refactoring some nasty code.
488dnl #
489AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG], [
490	ZFS_LINUX_TEST_SRC([bio_alloc_4arg], [
491		#include <linux/bio.h>
492	],[
493		gfp_t gfp_mask = 0;
494		unsigned short nr_iovecs = 0;
495		struct block_device *bdev = NULL;
496		unsigned int opf = 0;
497
498		struct bio *__attribute__((unused)) allocated = bio_alloc(bdev, nr_iovecs, opf, gfp_mask);
499	])
500])
501
502AC_DEFUN([ZFS_AC_KERNEL_BIO_ALLOC_4ARG], [
503	AC_MSG_CHECKING([whether bio_alloc() wants 4 args])
504	ZFS_LINUX_TEST_RESULT([bio_alloc_4arg],[
505		AC_MSG_RESULT(yes)
506		AC_DEFINE([HAVE_BIO_ALLOC_4ARG], 1, [bio_alloc() takes 4 arguments])
507	],[
508		AC_MSG_RESULT(no)
509	])
510])
511
512AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO], [
513	ZFS_AC_KERNEL_SRC_REQ
514	ZFS_AC_KERNEL_SRC_BIO_OPS
515	ZFS_AC_KERNEL_SRC_BIO_SET_DEV
516	ZFS_AC_KERNEL_SRC_BIO_END_IO_T_ARGS
517	ZFS_AC_KERNEL_SRC_BIO_BI_STATUS
518	ZFS_AC_KERNEL_SRC_BIO_BVEC_ITER
519	ZFS_AC_KERNEL_SRC_BIO_SUBMIT_BIO
520	ZFS_AC_KERNEL_SRC_BIO_CURRENT_BIO_LIST
521	ZFS_AC_KERNEL_SRC_BLKG_TRYGET
522	ZFS_AC_KERNEL_SRC_BIO_BDEV_DISK
523	ZFS_AC_KERNEL_SRC_BDEV_SUBMIT_BIO_RETURNS_VOID
524	ZFS_AC_KERNEL_SRC_BIO_SET_DEV_MACRO
525	ZFS_AC_KERNEL_SRC_BLK_CGROUP_HEADER
526	ZFS_AC_KERNEL_SRC_BIO_ALLOC_4ARG
527])
528
529AC_DEFUN([ZFS_AC_KERNEL_BIO], [
530	ZFS_AC_KERNEL_BIO_REQ_FAILFAST_MASK
531	ZFS_AC_KERNEL_BIO_REQ_DISCARD
532	ZFS_AC_KERNEL_BIO_REQ_FLUSH
533	ZFS_AC_KERNEL_BIO_REQ_PREFLUSH
534
535	ZFS_AC_KERNEL_BIO_REQ_OP_DISCARD
536	ZFS_AC_KERNEL_BIO_REQ_OP_SECURE_ERASE
537	ZFS_AC_KERNEL_BIO_REQ_OP_FLUSH
538	ZFS_AC_KERNEL_BIO_BI_OPF
539	ZFS_AC_KERNEL_BIO_SET_OP_ATTRS
540
541	ZFS_AC_KERNEL_BIO_SET_DEV
542	ZFS_AC_KERNEL_BIO_END_IO_T_ARGS
543	ZFS_AC_KERNEL_BIO_BI_STATUS
544	ZFS_AC_KERNEL_BIO_BVEC_ITER
545	ZFS_AC_KERNEL_BIO_SUBMIT_BIO
546	ZFS_AC_KERNEL_BIO_CURRENT_BIO_LIST
547	ZFS_AC_KERNEL_BLKG_TRYGET
548	ZFS_AC_KERNEL_BIO_BDEV_DISK
549	ZFS_AC_KERNEL_BDEV_SUBMIT_BIO_RETURNS_VOID
550	ZFS_AC_KERNEL_BLK_CGROUP_HEADER
551	ZFS_AC_KERNEL_BIO_ALLOC_4ARG
552])
553