aboutsummaryrefslogtreecommitdiffstats
path: root/config/kernel.m4
blob: 465f69b72b369c867c5db1362efd5687f7a08084 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
dnl #
dnl # Default ZFS kernel configuration
dnl #
AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
	AM_COND_IF([BUILD_LINUX], [
		dnl # Setup the kernel build environment.
		ZFS_AC_KERNEL
		ZFS_AC_QAT

		dnl # Sanity checks for module building and CONFIG_* defines
		ZFS_AC_KERNEL_CONFIG_DEFINED
		ZFS_AC_MODULE_SYMVERS

		dnl # Sequential ZFS_LINUX_TRY_COMPILE tests
		ZFS_AC_KERNEL_FPU_HEADER
		ZFS_AC_KERNEL_OBJTOOL_HEADER
		ZFS_AC_KERNEL_MISC_MINOR
		ZFS_AC_KERNEL_DECLARE_EVENT_CLASS

		dnl # Parallel ZFS_LINUX_TEST_SRC / ZFS_LINUX_TEST_RESULT tests
		ZFS_AC_KERNEL_TEST_SRC
		ZFS_AC_KERNEL_TEST_RESULT

		AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
			KERNEL_MAKE="$KERNEL_MAKE O=$LINUX_OBJ"
		])

		AC_SUBST(KERNEL_MAKE)
	])
])

dnl #
dnl # Generate and compile all of the kernel API test cases to determine
dnl # which interfaces are available.  By invoking the kernel build system
dnl # only once the compilation can be done in parallel significantly
dnl # speeding up the process.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
	ZFS_AC_KERNEL_SRC_TYPES
	ZFS_AC_KERNEL_SRC_OBJTOOL
	ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE
	ZFS_AC_KERNEL_SRC_PDE_DATA
	ZFS_AC_KERNEL_SRC_GENERIC_FADVISE
	ZFS_AC_KERNEL_SRC_SCHED
	ZFS_AC_KERNEL_SRC_USLEEP_RANGE
	ZFS_AC_KERNEL_SRC_VMALLOC_PAGE_KERNEL
	ZFS_AC_KERNEL_SRC_INODE_TIMES
	ZFS_AC_KERNEL_SRC_PROC_OPERATIONS
	ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS
	ZFS_AC_KERNEL_SRC_BIO
	ZFS_AC_KERNEL_SRC_BLKDEV
	ZFS_AC_KERNEL_SRC_BLK_QUEUE
	ZFS_AC_KERNEL_SRC_GENHD_FLAGS
	ZFS_AC_KERNEL_SRC_REVALIDATE_DISK
	ZFS_AC_KERNEL_SRC_GET_DISK_RO
	ZFS_AC_KERNEL_SRC_DISCARD_GRANULARITY
	ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE
	ZFS_AC_KERNEL_SRC_XATTR
	ZFS_AC_KERNEL_SRC_ACL
	ZFS_AC_KERNEL_SRC_INODE_SETATTR
	ZFS_AC_KERNEL_SRC_INODE_GETATTR
	ZFS_AC_KERNEL_SRC_SHOW_OPTIONS
	ZFS_AC_KERNEL_SRC_SHRINKER
	ZFS_AC_KERNEL_SRC_MKDIR
	ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS
	ZFS_AC_KERNEL_SRC_CREATE
	ZFS_AC_KERNEL_SRC_PERMISSION
	ZFS_AC_KERNEL_SRC_TMPFILE
	ZFS_AC_KERNEL_SRC_AUTOMOUNT
	ZFS_AC_KERNEL_SRC_COMMIT_METADATA
	ZFS_AC_KERNEL_SRC_SETATTR_PREPARE
	ZFS_AC_KERNEL_SRC_INSERT_INODE_LOCKED
	ZFS_AC_KERNEL_SRC_TRUNCATE_SETSIZE
	ZFS_AC_KERNEL_SRC_SECURITY_INODE
	ZFS_AC_KERNEL_SRC_FST_MOUNT
	ZFS_AC_KERNEL_SRC_SET_NLINK
	ZFS_AC_KERNEL_SRC_SGET
	ZFS_AC_KERNEL_SRC_VFS_FILEMAP_DIRTY_FOLIO
	ZFS_AC_KERNEL_SRC_VFS_READ_FOLIO
	ZFS_AC_KERNEL_SRC_VFS_FSYNC_2ARGS
	ZFS_AC_KERNEL_SRC_VFS_DIRECT_IO
	ZFS_AC_KERNEL_SRC_VFS_READPAGES
	ZFS_AC_KERNEL_SRC_VFS_SET_PAGE_DIRTY_NOBUFFERS
	ZFS_AC_KERNEL_SRC_VFS_IOV_ITER
	ZFS_AC_KERNEL_SRC_VFS_GENERIC_COPY_FILE_RANGE
	ZFS_AC_KERNEL_SRC_VFS_SPLICE_COPY_FILE_RANGE
	ZFS_AC_KERNEL_SRC_VFS_REMAP_FILE_RANGE
	ZFS_AC_KERNEL_SRC_VFS_CLONE_FILE_RANGE
	ZFS_AC_KERNEL_SRC_VFS_DEDUPE_FILE_RANGE
	ZFS_AC_KERNEL_SRC_KMAP_ATOMIC_ARGS
	ZFS_AC_KERNEL_SRC_KMAP_LOCAL_PAGE
	ZFS_AC_KERNEL_SRC_FOLLOW_DOWN_ONE
	ZFS_AC_KERNEL_SRC_MAKE_REQUEST_FN
	ZFS_AC_KERNEL_SRC_GENERIC_IO_ACCT
	ZFS_AC_KERNEL_SRC_FPU
	ZFS_AC_KERNEL_SRC_FMODE_T
	ZFS_AC_KERNEL_SRC_KUIDGID_T
	ZFS_AC_KERNEL_SRC_KUID_HELPERS
	ZFS_AC_KERNEL_SRC_RENAME
	ZFS_AC_KERNEL_SRC_TOTALRAM_PAGES_FUNC
	ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES
	ZFS_AC_KERNEL_SRC_PERCPU
	ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR
	ZFS_AC_KERNEL_SRC_MKNOD
	ZFS_AC_KERNEL_SRC_SYMLINK
	ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS
	ZFS_AC_KERNEL_SRC_SIGINFO
	ZFS_AC_KERNEL_SRC_SYSFS
	ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG
	ZFS_AC_KERNEL_SRC_STRLCPY
	ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
	ZFS_AC_KERNEL_SRC_ADD_DISK
	ZFS_AC_KERNEL_SRC_KTHREAD
	ZFS_AC_KERNEL_SRC_ZERO_PAGE
	ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
	ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
	ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS
	ZFS_AC_KERNEL_SRC_IATTR_VFSID
	ZFS_AC_KERNEL_SRC_WRITEPAGE_T
	ZFS_AC_KERNEL_SRC_RECLAIMED
	ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE
	ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_SZ
	ZFS_AC_KERNEL_SRC_PROC_HANDLER_CTL_TABLE_CONST
	ZFS_AC_KERNEL_SRC_COPY_SPLICE_READ
	ZFS_AC_KERNEL_SRC_SYNC_BDEV
	ZFS_AC_KERNEL_SRC_MM_PAGE_SIZE
	ZFS_AC_KERNEL_SRC_MM_PAGE_MAPPING
	case "$host_cpu" in
		powerpc*)
			ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
			ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
			;;
		riscv*)
			ZFS_AC_KERNEL_SRC_FLUSH_DCACHE_PAGE
			;;
	esac

	AC_MSG_CHECKING([for available kernel interfaces])
	ZFS_LINUX_TEST_COMPILE_ALL([kabi])
	AC_MSG_RESULT([done])
])

dnl #
dnl # Check results of kernel interface tests.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
	ZFS_AC_KERNEL_TYPES
	ZFS_AC_KERNEL_ACCESS_OK_TYPE
	ZFS_AC_KERNEL_OBJTOOL
	ZFS_AC_KERNEL_PDE_DATA
	ZFS_AC_KERNEL_GENERIC_FADVISE
	ZFS_AC_KERNEL_SCHED
	ZFS_AC_KERNEL_USLEEP_RANGE
	ZFS_AC_KERNEL_VMALLOC_PAGE_KERNEL
	ZFS_AC_KERNEL_INODE_TIMES
	ZFS_AC_KERNEL_PROC_OPERATIONS
	ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS
	ZFS_AC_KERNEL_BIO
	ZFS_AC_KERNEL_BLKDEV
	ZFS_AC_KERNEL_BLK_QUEUE
	ZFS_AC_KERNEL_GENHD_FLAGS
	ZFS_AC_KERNEL_REVALIDATE_DISK
	ZFS_AC_KERNEL_GET_DISK_RO
	ZFS_AC_KERNEL_DISCARD_GRANULARITY
	ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE
	ZFS_AC_KERNEL_XATTR
	ZFS_AC_KERNEL_ACL
	ZFS_AC_KERNEL_INODE_SETATTR
	ZFS_AC_KERNEL_INODE_GETATTR
	ZFS_AC_KERNEL_SHOW_OPTIONS
	ZFS_AC_KERNEL_SHRINKER
	ZFS_AC_KERNEL_MKDIR
	ZFS_AC_KERNEL_LOOKUP_FLAGS
	ZFS_AC_KERNEL_CREATE
	ZFS_AC_KERNEL_PERMISSION
	ZFS_AC_KERNEL_TMPFILE
	ZFS_AC_KERNEL_AUTOMOUNT
	ZFS_AC_KERNEL_COMMIT_METADATA
	ZFS_AC_KERNEL_SETATTR_PREPARE
	ZFS_AC_KERNEL_INSERT_INODE_LOCKED
	ZFS_AC_KERNEL_TRUNCATE_SETSIZE
	ZFS_AC_KERNEL_SECURITY_INODE
	ZFS_AC_KERNEL_FST_MOUNT
	ZFS_AC_KERNEL_SET_NLINK
	ZFS_AC_KERNEL_SGET
	ZFS_AC_KERNEL_VFS_FILEMAP_DIRTY_FOLIO
	ZFS_AC_KERNEL_VFS_READ_FOLIO
	ZFS_AC_KERNEL_VFS_FSYNC_2ARGS
	ZFS_AC_KERNEL_VFS_DIRECT_IO
	ZFS_AC_KERNEL_VFS_READPAGES
	ZFS_AC_KERNEL_VFS_SET_PAGE_DIRTY_NOBUFFERS
	ZFS_AC_KERNEL_VFS_IOV_ITER
	ZFS_AC_KERNEL_VFS_GENERIC_COPY_FILE_RANGE
	ZFS_AC_KERNEL_VFS_SPLICE_COPY_FILE_RANGE
	ZFS_AC_KERNEL_VFS_REMAP_FILE_RANGE
	ZFS_AC_KERNEL_VFS_CLONE_FILE_RANGE
	ZFS_AC_KERNEL_VFS_DEDUPE_FILE_RANGE
	ZFS_AC_KERNEL_KMAP_ATOMIC_ARGS
	ZFS_AC_KERNEL_KMAP_LOCAL_PAGE
	ZFS_AC_KERNEL_FOLLOW_DOWN_ONE
	ZFS_AC_KERNEL_MAKE_REQUEST_FN
	ZFS_AC_KERNEL_GENERIC_IO_ACCT
	ZFS_AC_KERNEL_FPU
	ZFS_AC_KERNEL_FMODE_T
	ZFS_AC_KERNEL_KUIDGID_T
	ZFS_AC_KERNEL_KUID_HELPERS
	ZFS_AC_KERNEL_RENAME
	ZFS_AC_KERNEL_TOTALRAM_PAGES_FUNC
	ZFS_AC_KERNEL_TOTALHIGH_PAGES
	ZFS_AC_KERNEL_PERCPU
	ZFS_AC_KERNEL_GENERIC_FILLATTR
	ZFS_AC_KERNEL_MKNOD
	ZFS_AC_KERNEL_SYMLINK
	ZFS_AC_KERNEL_BIO_MAX_SEGS
	ZFS_AC_KERNEL_SIGINFO
	ZFS_AC_KERNEL_SYSFS
	ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG
	ZFS_AC_KERNEL_STRLCPY
	ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
	ZFS_AC_KERNEL_ADD_DISK
	ZFS_AC_KERNEL_KTHREAD
	ZFS_AC_KERNEL_ZERO_PAGE
	ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
	ZFS_AC_KERNEL_IDMAP_MNT_API
	ZFS_AC_KERNEL_IDMAP_NO_USERNS
	ZFS_AC_KERNEL_IATTR_VFSID
	ZFS_AC_KERNEL_WRITEPAGE_T
	ZFS_AC_KERNEL_RECLAIMED
	ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE
	ZFS_AC_KERNEL_REGISTER_SYSCTL_SZ
	ZFS_AC_KERNEL_PROC_HANDLER_CTL_TABLE_CONST
	ZFS_AC_KERNEL_COPY_SPLICE_READ
	ZFS_AC_KERNEL_SYNC_BDEV
	ZFS_AC_KERNEL_MM_PAGE_SIZE
	ZFS_AC_KERNEL_MM_PAGE_MAPPING
	ZFS_AC_KERNEL_1ARG_ASSIGN_STR
	case "$host_cpu" in
		powerpc*)
			ZFS_AC_KERNEL_CPU_HAS_FEATURE
			ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
			;;
		riscv*)
			ZFS_AC_KERNEL_FLUSH_DCACHE_PAGE
			;;
	esac
])

dnl #
dnl # Detect name used for Module.symvers file in kernel
dnl #
AC_DEFUN([ZFS_AC_MODULE_SYMVERS], [
	modpost=$LINUX/scripts/Makefile.modpost
	AC_MSG_CHECKING([kernel file name for module symbols])
	AS_IF([test "x$enable_linux_builtin" != xyes -a -f "$modpost"], [
		AS_IF([grep -q Modules.symvers $modpost], [
			LINUX_SYMBOLS=Modules.symvers
		], [
			LINUX_SYMBOLS=Module.symvers
		])

		AS_IF([test ! -f "$LINUX_OBJ/$LINUX_SYMBOLS"], [
			AC_MSG_ERROR([
	*** Please make sure the kernel devel package for your distribution
	*** is installed.  If you are building with a custom kernel, make sure
	*** the kernel is configured, built, and the '--with-linux=PATH'
	*** configure option refers to the location of the kernel source.
			])
		])
	], [
		LINUX_SYMBOLS=NONE
	])
	AC_MSG_RESULT($LINUX_SYMBOLS)
	AC_SUBST(LINUX_SYMBOLS)
])

dnl #
dnl # Detect the kernel to be built against
dnl #
dnl # Most modern Linux distributions have separate locations for bare
dnl # source (source) and prebuilt (build) files. Additionally, there are
dnl # `source` and `build` symlinks in `/lib/modules/$(KERNEL_VERSION)`
dnl # pointing to them. The directory search order is now:
dnl # 
dnl # - `configure` command line values if both `--with-linux` and
dnl #   `--with-linux-obj` were defined
dnl # 
dnl # - If only `--with-linux` was defined, `--with-linux-obj` is assumed
dnl #   to have the same value as `--with-linux`
dnl # 
dnl # - If neither `--with-linux` nor `--with-linux-obj` were defined
dnl #   autodetection is used:
dnl # 
dnl #   - `/lib/modules/$(uname -r)/{source,build}` respectively, if exist.
dnl # 
dnl #   - If only `/lib/modules/$(uname -r)/build` exists, it is assumed
dnl #     to be both source and build directory.
dnl # 
dnl #   - The first directory in `/lib/modules` with the highest version
dnl #     number according to `sort -V` which contains both `source` and
dnl #     `build` symlinks/directories. If module directory contains only
dnl #     `build` component, it is assumed to be both source and build
dnl #     directory.
dnl # 
dnl #   - Last resort: the first directory matching `/usr/src/kernels/*`
dnl #     and `/usr/src/linux-*` with the highest version number according
dnl #     to `sort -V` is assumed to be both source and build directory.
dnl #
AC_DEFUN([ZFS_AC_KERNEL], [
	AC_ARG_WITH([linux],
		AS_HELP_STRING([--with-linux=PATH],
		[Path to kernel source]),
		[kernelsrc="$withval"])

	AC_ARG_WITH(linux-obj,
		AS_HELP_STRING([--with-linux-obj=PATH],
		[Path to kernel build objects]),
		[kernelbuild="$withval"])

	AC_MSG_CHECKING([kernel source and build directories])
	AS_IF([test -n "$kernelsrc" && test -z "$kernelbuild"], [
		kernelbuild="$kernelsrc"
	], [test -z "$kernelsrc"], [
		AS_IF([test -e "/lib/modules/$(uname -r)/source" && \
		       test -e "/lib/modules/$(uname -r)/build"], [
			src="/lib/modules/$(uname -r)/source"
			build="/lib/modules/$(uname -r)/build"
		], [test -e "/lib/modules/$(uname -r)/build"], [
			build="/lib/modules/$(uname -r)/build"
			src="$build"
		], [
			src=

			for d in $(ls -1d /lib/modules/* 2>/dev/null | sort -Vr); do
				if test -e "$d/source" && test -e "$d/build"; then
					src="$d/source"
					build="$d/build"
					break
				fi

				if test -e "$d/build"; then
					src="$d/build"
					build="$d/build"
					break
				fi
			done

			# the least reliable method
			if test -z "$src"; then
				src=$(ls -1d /usr/src/kernels/* /usr/src/linux-* \
				      2>/dev/null | grep -v obj | sort -Vr | head -1)
				build="$src"
			fi
		])

		AS_IF([test -n "$src" && test -e "$src"], [
			kernelsrc=$(readlink -e "$src")
		], [
			kernelsrc="[Not found]"
		])
		AS_IF([test -n "$build" && test -e "$build"], [
			kernelbuild=$(readlink -e "$build")
		], [
			kernelbuild="[Not found]"
		])
	], [
		AS_IF([test "$kernelsrc" = "NONE"], [
			kernsrcver=NONE
		])
		withlinux=yes
	])

	AC_MSG_RESULT([done])
	AC_MSG_CHECKING([kernel source directory])
	AC_MSG_RESULT([$kernelsrc])
	AC_MSG_CHECKING([kernel build directory])
	AC_MSG_RESULT([$kernelbuild])
	AS_IF([test ! -d "$kernelsrc" || test ! -d "$kernelbuild"], [
		AC_MSG_ERROR([
	*** Please make sure the kernel devel package for your distribution
	*** is installed and then try again.  If that fails, you can specify the
	*** location of the kernel source and build with the '--with-linux=PATH' and
	*** '--with-linux-obj=PATH' options respectively.])
	])

	AC_MSG_CHECKING([kernel source version])
	utsrelease1=$kernelbuild/include/linux/version.h
	utsrelease2=$kernelbuild/include/linux/utsrelease.h
	utsrelease3=$kernelbuild/include/generated/utsrelease.h
	AS_IF([test -r $utsrelease1 && grep -qF UTS_RELEASE $utsrelease1], [
		utsrelease=$utsrelease1
	], [test -r $utsrelease2 && grep -qF UTS_RELEASE $utsrelease2], [
		utsrelease=$utsrelease2
	], [test -r $utsrelease3 && grep -qF UTS_RELEASE $utsrelease3], [
		utsrelease=$utsrelease3
	])

	AS_IF([test -n "$utsrelease"], [
		kernsrcver=$($AWK '/UTS_RELEASE/ { gsub(/"/, "", $[3]); print $[3] }' $utsrelease)
		AS_IF([test -z "$kernsrcver"], [
			AC_MSG_RESULT([Not found])
			AC_MSG_ERROR([
	*** Cannot determine kernel version.
			])
		])
	], [
		AC_MSG_RESULT([Not found])
		if test "x$enable_linux_builtin" != xyes; then
			AC_MSG_ERROR([
	*** Cannot find UTS_RELEASE definition.
			])
		else
			AC_MSG_ERROR([
	*** Cannot find UTS_RELEASE definition.
	*** Please run 'make prepare' inside the kernel source tree.])
		fi
	])

	AC_MSG_RESULT([$kernsrcver])

	AS_VERSION_COMPARE([$kernsrcver], [$ZFS_META_KVER_MIN], [
		 AC_MSG_ERROR([
	*** Cannot build against kernel version $kernsrcver.
	*** The minimum supported kernel version is $ZFS_META_KVER_MIN.
		])
	])

	LINUX=${kernelsrc}
	LINUX_OBJ=${kernelbuild}
	LINUX_VERSION=${kernsrcver}

	AC_SUBST(LINUX)
	AC_SUBST(LINUX_OBJ)
	AC_SUBST(LINUX_VERSION)
])

dnl #
dnl # Detect the QAT module to be built against, QAT provides hardware
dnl # acceleration for data compression:
dnl #
dnl # https://01.org/intel-quickassist-technology
dnl #
dnl # 1) Download and install QAT driver from the above link
dnl # 2) Start QAT driver in your system:
dnl # 	 service qat_service start
dnl # 3) Enable QAT in ZFS, e.g.:
dnl # 	 ./configure --with-qat=<qat-driver-path>/QAT1.6
dnl # 	 make
dnl # 4) Set GZIP compression in ZFS dataset:
dnl # 	 zfs set compression = gzip <dataset>
dnl #
dnl # Then the data written to this ZFS pool is compressed by QAT accelerator
dnl # automatically, and de-compressed by QAT when read from the pool.
dnl #
dnl # 1) Get QAT hardware statistics with:
dnl #	 cat /proc/icp_dh895xcc_dev/qat
dnl # 2) To disable QAT:
dnl # 	 insmod zfs.ko zfs_qat_disable=1
dnl #
AC_DEFUN([ZFS_AC_QAT], [
	AC_ARG_WITH([qat],
		AS_HELP_STRING([--with-qat=PATH],
		[Path to qat source]),
		AS_IF([test "$withval" = "yes"],
			AC_MSG_ERROR([--with-qat=PATH requires a PATH]),
			[qatsrc="$withval"]))

	AC_ARG_WITH([qat-obj],
		AS_HELP_STRING([--with-qat-obj=PATH],
		[Path to qat build objects]),
		[qatbuild="$withval"])

	AS_IF([test ! -z "${qatsrc}"], [
		AC_MSG_CHECKING([qat source directory])
		AC_MSG_RESULT([$qatsrc])
		QAT_SRC="${qatsrc}/quickassist"
		AS_IF([ test ! -e "$QAT_SRC/include/cpa.h"], [
			AC_MSG_ERROR([
	*** Please make sure the qat driver package is installed
	*** and specify the location of the qat source with the
	*** '--with-qat=PATH' option then try again. Failed to
	*** find cpa.h in:
	${QAT_SRC}/include])
		])
	])

	AS_IF([test ! -z "${qatsrc}"], [
		AC_MSG_CHECKING([qat build directory])
		AS_IF([test -z "$qatbuild"], [
			qatbuild="${qatsrc}/build"
		])

		AC_MSG_RESULT([$qatbuild])
		QAT_OBJ=${qatbuild}
		AS_IF([ ! test -e "$QAT_OBJ/icp_qa_al.ko" && ! test -e "$QAT_OBJ/qat_api.ko"], [
			AC_MSG_ERROR([
	*** Please make sure the qat driver is installed then try again.
	*** Failed to find icp_qa_al.ko or qat_api.ko in:
	$QAT_OBJ])
		])

		AC_SUBST(QAT_SRC)
		AC_SUBST(QAT_OBJ)

		AC_DEFINE(HAVE_QAT, 1,
		[qat is enabled and existed])
	])

	dnl #
	dnl # Detect the name used for the QAT Module.symvers file.
	dnl #
	AS_IF([test ! -z "${qatsrc}"], [
		AC_MSG_CHECKING([qat file for module symbols])
		QAT_SYMBOLS=$QAT_SRC/lookaside/access_layer/src/Module.symvers

		AS_IF([test -r $QAT_SYMBOLS], [
			AC_MSG_RESULT([$QAT_SYMBOLS])
			AC_SUBST(QAT_SYMBOLS)
		],[
			AC_MSG_ERROR([
	*** Please make sure the qat driver is installed then try again.
	*** Failed to find Module.symvers in:
	$QAT_SYMBOLS
			])
		])
	])
])

dnl #
dnl # ZFS_LINUX_CONFTEST_H
dnl #
AC_DEFUN([ZFS_LINUX_CONFTEST_H], [
test -d build/$2 || mkdir -p build/$2
cat - <<_ACEOF >build/$2/$2.h
$1
_ACEOF
])

dnl #
dnl # ZFS_LINUX_CONFTEST_C
dnl #
AC_DEFUN([ZFS_LINUX_CONFTEST_C], [
test -d build/$2 || mkdir -p build/$2
cat confdefs.h - <<_ACEOF >build/$2/$2.c
$1
_ACEOF
])

dnl #
dnl # ZFS_LINUX_CONFTEST_MAKEFILE
dnl #
dnl # $1 - test case name
dnl # $2 - add to top-level Makefile
dnl # $3 - additional build flags
dnl #
AC_DEFUN([ZFS_LINUX_CONFTEST_MAKEFILE], [
	test -d build || mkdir -p build
	test -d build/$1 || mkdir -p build/$1

	file=build/$1/Makefile

	dnl # Example command line to manually build source.
	cat - <<_ACEOF >$file
# Example command line to manually build source
# make modules -C $LINUX_OBJ $ARCH_UM M=$PWD/build/$1

ccflags-y := -Werror $FRAME_LARGER_THAN
_ACEOF

	dnl # Additional custom CFLAGS as requested.
	m4_ifval($3, [echo "ccflags-y += $3" >>$file], [])

	dnl # Test case source
	echo "obj-m := $1.o" >>$file

	AS_IF([test "x$2" = "xyes"], [echo "obj-m += $1/" >>build/Makefile], [])
])

dnl #
dnl # ZFS_LINUX_TEST_PROGRAM(C)([PROLOGUE], [BODY])
dnl #
m4_define([ZFS_LINUX_TEST_PROGRAM], [
#include <linux/module.h>
$1

int
main (void)
{
$2
	;
	return 0;
}

MODULE_DESCRIPTION("conftest");
MODULE_AUTHOR(ZFS_META_AUTHOR);
MODULE_VERSION(ZFS_META_VERSION "-" ZFS_META_RELEASE);
MODULE_LICENSE($3);
])

dnl #
dnl # ZFS_LINUX_TEST_REMOVE
dnl #
dnl # Removes the specified test source and results.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_REMOVE], [
	test -d build/$1 && rm -Rf build/$1
	test -f build/Makefile && sed '/$1/d' build/Makefile
])

dnl #
dnl # ZFS_LINUX_COMPILE
dnl #
dnl # $1 - build dir
dnl # $2 - test command
dnl # $3 - pass command
dnl # $4 - fail command
dnl # $5 - set KBUILD_MODPOST_NOFINAL='yes'
dnl # $6 - set KBUILD_MODPOST_WARN='yes'
dnl #
dnl # Used internally by ZFS_LINUX_TEST_{COMPILE,MODPOST}
dnl #
AC_DEFUN([ZFS_LINUX_COMPILE], [
	AC_ARG_VAR([KERNEL_CC], [C compiler for
		building kernel modules])
	AC_ARG_VAR([KERNEL_LD], [Linker for
		building kernel modules])
	AC_ARG_VAR([KERNEL_LLVM], [Binary option to
		build kernel modules with LLVM/CLANG toolchain])
	AC_TRY_COMMAND([
	    KBUILD_MODPOST_NOFINAL="$5" KBUILD_MODPOST_WARN="$6"
	    make modules -k -j$TEST_JOBS ${KERNEL_CC:+CC=$KERNEL_CC}
	    ${KERNEL_LD:+LD=$KERNEL_LD} ${KERNEL_LLVM:+LLVM=$KERNEL_LLVM}
	    CONFIG_MODULES=y CFLAGS_MODULE=-DCONFIG_MODULES
	    -C $LINUX_OBJ $ARCH_UM M=$PWD/$1 >$1/build.log 2>&1])
	AS_IF([AC_TRY_COMMAND([$2])], [$3], [$4])
])

dnl #
dnl # ZFS_LINUX_TEST_COMPILE
dnl #
dnl # Perform a full compile excluding the final modpost phase.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_COMPILE], [
	ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
		mv $2/Makefile $2/Makefile.compile.$1
		mv $2/build.log $2/build.log.$1
	],[
	        AC_MSG_ERROR([
        *** Unable to compile test source to determine kernel interfaces.])
	], [yes], [])
])

dnl #
dnl # ZFS_LINUX_TEST_MODPOST
dnl #
dnl # Perform a full compile including the modpost phase.  This may
dnl # be an incremental build if the objects have already been built.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_MODPOST], [
	ZFS_LINUX_COMPILE([$2], [test -f $2/build.log], [
		mv $2/Makefile $2/Makefile.modpost.$1
		cat $2/build.log >>build/build.log.$1
	],[
	        AC_MSG_ERROR([
        *** Unable to modpost test source to determine kernel interfaces.])
	], [], [yes])
])

dnl #
dnl # Perform the compilation of the test cases in two phases.
dnl #
dnl # Phase 1) attempt to build the object files for all of the tests
dnl #          defined by the ZFS_LINUX_TEST_SRC macro.  But do not
dnl #          perform the final modpost stage.
dnl #
dnl # Phase 2) disable all tests which failed the initial compilation,
dnl #          then invoke the final modpost step for the remaining tests.
dnl #
dnl # This allows us efficiently build the test cases in parallel while
dnl # remaining resilient to build failures which are expected when
dnl # detecting the available kernel interfaces.
dnl #
dnl # The maximum allowed parallelism can be controlled by setting the
dnl # TEST_JOBS environment variable.  Otherwise, it default to $(nproc).
dnl #
AC_DEFUN([ZFS_LINUX_TEST_COMPILE_ALL], [
	dnl # Phase 1 - Compilation only, final linking is skipped.
	ZFS_LINUX_TEST_COMPILE([$1], [build])

	dnl #
	dnl # Phase 2 - When building external modules disable test cases
	dnl # which failed to compile and invoke modpost to verify the
	dnl # final linking.
	dnl #
	dnl # Test names suffixed with '_license' call modpost independently
	dnl # to ensure that a single incompatibility does not result in the
	dnl # modpost phase exiting early.  This check is not performed on
	dnl # every symbol since the majority are compatible and doing so
	dnl # would significantly slow down this phase.
	dnl #
	dnl # When configuring for builtin (--enable-linux-builtin)
	dnl # fake the linking step artificially create the expected .ko
	dnl # files for tests which did compile.  This is required for
	dnl # kernels which do not have loadable module support or have
	dnl # not yet been built.
	dnl #
	AS_IF([test "x$enable_linux_builtin" = "xno"], [
		for dir in $(awk '/^obj-m/ { print [$]3 }' \
		    build/Makefile.compile.$1); do
			name=${dir%/}
			AS_IF([test -f build/$name/$name.o], [
				AS_IF([test "${name##*_}" = "license"], [
					ZFS_LINUX_TEST_MODPOST([$1],
					    [build/$name])
					echo "obj-n += $dir" >>build/Makefile
				], [
					echo "obj-m += $dir" >>build/Makefile
				])
			], [
				echo "obj-n += $dir" >>build/Makefile
			])
		done

		ZFS_LINUX_TEST_MODPOST([$1], [build])
	], [
		for dir in $(awk '/^obj-m/ { print [$]3 }' \
		    build/Makefile.compile.$1); do
			name=${dir%/}
			AS_IF([test -f build/$name/$name.o], [
				touch build/$name/$name.ko
			])
		done
	])
])

dnl #
dnl # ZFS_LINUX_TEST_SRC
dnl #
dnl # $1 - name
dnl # $2 - global
dnl # $3 - source
dnl # $4 - extra cflags
dnl # $5 - check license-compatibility
dnl #
dnl # Check if the test source is buildable at all and then if it is
dnl # license compatible.
dnl #
dnl # N.B because all of the test cases are compiled in parallel they
dnl # must never depend on the results of previous tests.  Each test
dnl # needs to be entirely independent.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_SRC], [
	ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM([[$2]], [[$3]],
	    [["Dual BSD/GPL"]])], [$1])
	ZFS_LINUX_CONFTEST_MAKEFILE([$1], [yes], [$4])

	AS_IF([ test -n "$5" ], [
		ZFS_LINUX_CONFTEST_C([ZFS_LINUX_TEST_PROGRAM(
		    [[$2]], [[$3]], [[$5]])], [$1_license])
		ZFS_LINUX_CONFTEST_MAKEFILE([$1_license], [yes], [$4])
	])
])

dnl #
dnl # ZFS_LINUX_TEST_RESULT
dnl #
dnl # $1 - name of a test source (ZFS_LINUX_TEST_SRC)
dnl # $2 - run on success (valid .ko generated)
dnl # $3 - run on failure (unable to compile)
dnl #
AC_DEFUN([ZFS_LINUX_TEST_RESULT], [
	AS_IF([test -d build/$1], [
		AS_IF([test -f build/$1/$1.ko], [$2], [$3])
	], [
		AC_MSG_ERROR([
	*** No matching source for the "$1" test, check that
	*** both the test source and result macros refer to the same name.
		])
	])
])

dnl #
dnl # ZFS_LINUX_TEST_ERROR
dnl #
dnl # Generic error message which can be used when none of the expected
dnl # kernel interfaces were detected.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_ERROR], [
	AC_MSG_ERROR([
	*** None of the expected "$1" interfaces were detected.
	*** This may be because your kernel version is newer than what is
	*** supported, or you are using a patched custom kernel with
	*** incompatible modifications.
	***
	*** ZFS Version: $ZFS_META_ALIAS
	*** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
	])
])

dnl #
dnl # ZFS_LINUX_TEST_RESULT_SYMBOL
dnl #
dnl # Like ZFS_LINUX_TEST_RESULT except ZFS_CHECK_SYMBOL_EXPORT is called to
dnl # verify symbol exports, unless --enable-linux-builtin was provided to
dnl # configure.
dnl #
AC_DEFUN([ZFS_LINUX_TEST_RESULT_SYMBOL], [
	AS_IF([ ! test -f build/$1/$1.ko], [
		$5
	], [
		AS_IF([test "x$enable_linux_builtin" != "xyes"], [
			ZFS_CHECK_SYMBOL_EXPORT([$2], [$3], [$4], [$5])
		], [
			$4
		])
	])
])

dnl #
dnl # ZFS_LINUX_COMPILE_IFELSE
dnl #
AC_DEFUN([ZFS_LINUX_COMPILE_IFELSE], [
	ZFS_LINUX_TEST_REMOVE([conftest])

	m4_ifvaln([$1], [ZFS_LINUX_CONFTEST_C([$1], [conftest])])
	m4_ifvaln([$5], [ZFS_LINUX_CONFTEST_H([$5], [conftest])],
	    [ZFS_LINUX_CONFTEST_H([], [conftest])])

	ZFS_LINUX_CONFTEST_MAKEFILE([conftest], [no],
	    [m4_ifvaln([$5], [-I$PWD/build/conftest], [])])
	ZFS_LINUX_COMPILE([build/conftest], [$2], [$3], [$4], [], [])
])

dnl #
dnl # ZFS_LINUX_TRY_COMPILE
dnl #
dnl # $1 - global
dnl # $2 - source
dnl # $3 - run on success (valid .ko generated)
dnl # $4 - run on failure (unable to compile)
dnl #
dnl # When configuring as builtin (--enable-linux-builtin) for kernels
dnl # without loadable module support (CONFIG_MODULES=n) only the object
dnl # file is created.  See ZFS_LINUX_TEST_COMPILE_ALL for details.
dnl #
AC_DEFUN([ZFS_LINUX_TRY_COMPILE], [
	AS_IF([test "x$enable_linux_builtin" = "xyes"], [
		ZFS_LINUX_COMPILE_IFELSE(
		    [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]],
		    [[ZFS_META_LICENSE]])],
		    [test -f build/conftest/conftest.o], [$3], [$4])
	], [
		ZFS_LINUX_COMPILE_IFELSE(
		    [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]],
		    [[ZFS_META_LICENSE]])],
		    [test -f build/conftest/conftest.ko], [$3], [$4])
	])
])

dnl #
dnl # ZFS_CHECK_SYMBOL_EXPORT
dnl #
dnl # Check if a symbol is exported on not by consulting the symbols
dnl # file, or optionally the source code.
dnl #
AC_DEFUN([ZFS_CHECK_SYMBOL_EXPORT], [
	grep -q -E '[[[:space:]]]$1[[[:space:]]]' \
		$LINUX_OBJ/$LINUX_SYMBOLS 2>/dev/null
	rc=$?
	if test $rc -ne 0; then
		export=0
		for file in $2; do
			grep -q -E "EXPORT_SYMBOL.*($1)" \
				"$LINUX/$file" 2>/dev/null
			rc=$?
			if test $rc -eq 0; then
				export=1
				break;
			fi
		done
		if test $export -eq 0; then :
			$4
		else :
			$3
		fi
	else :
		$3
	fi
])

dnl #
dnl # ZFS_LINUX_TRY_COMPILE_SYMBOL
dnl #
dnl # Like ZFS_LINUX_TRY_COMPILER except ZFS_CHECK_SYMBOL_EXPORT is called
dnl # to verify symbol exports, unless --enable-linux-builtin was provided
dnl # to configure.
dnl #
AC_DEFUN([ZFS_LINUX_TRY_COMPILE_SYMBOL], [
	ZFS_LINUX_TRY_COMPILE([$1], [$2], [rc=0], [rc=1])
	if test $rc -ne 0; then :
		$6
	else
		if test "x$enable_linux_builtin" != xyes; then
			ZFS_CHECK_SYMBOL_EXPORT([$3], [$4], [rc=0], [rc=1])
		fi
		if test $rc -ne 0; then :
			$6
		else :
			$5
		fi
	fi
])

dnl #
dnl # ZFS_LINUX_TRY_COMPILE_HEADER
dnl # like ZFS_LINUX_TRY_COMPILE, except the contents conftest.h are
dnl # provided via the fifth parameter
dnl #
AC_DEFUN([ZFS_LINUX_TRY_COMPILE_HEADER], [
	AS_IF([test "x$enable_linux_builtin" = "xyes"], [
		ZFS_LINUX_COMPILE_IFELSE(
		    [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]],
		    [[ZFS_META_LICENSE]])],
		    [test -f build/conftest/conftest.o], [$3], [$4], [$5])
	], [
		ZFS_LINUX_COMPILE_IFELSE(
		    [ZFS_LINUX_TEST_PROGRAM([[$1]], [[$2]],
		    [[ZFS_META_LICENSE]])],
		    [test -f build/conftest/conftest.ko], [$3], [$4], [$5])
	])
])

dnl #
dnl # AS_VERSION_COMPARE_LE
dnl # like AS_VERSION_COMPARE_LE, but runs $3 if (and only if) $1 <= $2
dnl # AS_VERSION_COMPARE_LE (version-1, version-2, [action-if-less-or-equal], [action-if-greater])
dnl #
AC_DEFUN([AS_VERSION_COMPARE_LE], [
	AS_VERSION_COMPARE([$1], [$2], [$3], [$3], [$4])
])

dnl #
dnl # ZFS_LINUX_REQUIRE_API
dnl # like ZFS_LINUX_TEST_ERROR, except only fails if the kernel is
dnl # at least some specified version.
dnl #
AC_DEFUN([ZFS_LINUX_REQUIRE_API], [
	AS_VERSION_COMPARE_LE([$2], [$kernsrcver], [
		AC_MSG_ERROR([
		*** None of the expected "$1" interfaces were detected. This
		*** interface is expected for kernels version "$2" and above.
		*** This may be because your kernel version is newer than what is
		*** supported, or you are using a patched custom kernel with
		*** incompatible modifications.  Newer kernels may have incompatible
		*** APIs.
		***
		*** ZFS Version: $ZFS_META_ALIAS
		*** Compatible Kernels: $ZFS_META_KVER_MIN - $ZFS_META_KVER_MAX
		])
	], [
		AC_MSG_RESULT(no)
	])
])