diff --git a/sys/conf/files b/sys/conf/files
index c127ce7e7103..51d052e3c31d 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,5232 +1,5233 @@
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
 # dependency lines other than the first are silently ignored.
 #
 acpi_quirks.h			optional acpi				   \
 	dependency	"$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \
 	compile-with	"${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"acpi_quirks.h"
 bhnd_nvram_map.h		optional bhnd				   \
 	dependency	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
 	compile-with	"sh $S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"bhnd_nvram_map.h"
 bhnd_nvram_map_data.h		optional bhnd				   \
 	dependency	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
 	compile-with	"sh $S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"bhnd_nvram_map_data.h"
 fdt_static_dtb.h		optional fdt fdt_dtb_static \
 	compile-with "sh -c 'MACHINE=${MACHINE} $S/tools/fdt/make_dtbh.sh ${FDT_DTS_FILE} ${.CURDIR}'" \
 	dependency	"${FDT_DTS_FILE:T:R}.dtb" \
 	no-obj no-implicit-rule before-depend \
 	clean		"fdt_static_dtb.h"
 feeder_eq_gen.h			optional sound				   \
 	dependency	"$S/tools/sound/feeder_eq_mkfilter.awk"		   \
 	compile-with	"${AWK} -f $S/tools/sound/feeder_eq_mkfilter.awk -- ${FEEDER_EQ_PRESETS} > feeder_eq_gen.h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"feeder_eq_gen.h"
 feeder_rate_gen.h		optional sound				   \
 	dependency	"$S/tools/sound/feeder_rate_mkfilter.awk"	   \
 	compile-with	"${AWK} -f $S/tools/sound/feeder_rate_mkfilter.awk -- ${FEEDER_RATE_PRESETS} > feeder_rate_gen.h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"feeder_rate_gen.h"
 font.h				optional	sc_dflt_font		\
 	compile-with	"uudecode < ${SRCTOP}/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < ${SRCTOP}/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < ${SRCTOP}/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h"									\
 	no-obj no-implicit-rule before-depend				\
 	clean		"font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8"
 snd_fxdiv_gen.h			optional sound				   \
 	dependency	"$S/tools/sound/snd_fxdiv_gen.awk"		   \
 	compile-with	"${AWK} -f $S/tools/sound/snd_fxdiv_gen.awk -- > snd_fxdiv_gen.h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"snd_fxdiv_gen.h"
 miidevs.h			optional miibus | mii			   \
 	dependency	"$S/tools/miidevs2h.awk $S/dev/mii/miidevs"	   \
 	compile-with	"${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"miidevs.h"
 kbdmuxmap.h			optional	kbdmux_dflt_keymap 	   \
 	compile-with	"${KEYMAP} -L ${KBDMUX_DFLT_KEYMAP} | ${KEYMAP_FIX} > ${.TARGET}" \
 	no-obj no-implicit-rule before-depend				\
 	clean		"kbdmuxmap.h"
 teken_state.h		optional sc | vt				   \
 	dependency	"$S/teken/gensequences $S/teken/sequences" \
 	compile-with	"${AWK} -f $S/teken/gensequences $S/teken/sequences > teken_state.h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"teken_state.h"
 ukbdmap.h			optional	ukbd_dflt_keymap	\
 	compile-with	"${KEYMAP} -L ${UKBD_DFLT_KEYMAP} | ${KEYMAP_FIX} > ${.TARGET}" \
 	no-obj no-implicit-rule before-depend				\
 	clean		"ukbdmap.h"
 usbdevs.h			optional usb | hid			   \
 	dependency	"$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \
 	compile-with	"${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"usbdevs.h"
 usbdevs_data.h			optional usb				   \
 	dependency	"$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \
 	compile-with	"${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"usbdevs_data.h"
 sdiodevs.h			optional mmccam				   \
 	dependency	"$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \
 	compile-with	"${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -h" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"sdiodevs.h"
 sdiodevs_data.h			optional mmccam				   \
 	dependency	"$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \
 	compile-with	"${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -d" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"sdiodevs_data.h"
 cam/cam.c			optional scbus
 cam/cam_compat.c		optional scbus
 cam/cam_iosched.c		optional scbus
 cam/cam_periph.c		optional scbus
 cam/cam_queue.c			optional scbus
 cam/cam_sim.c			optional scbus
 cam/cam_xpt.c			optional scbus
 cam/ata/ata_all.c		optional scbus
 cam/ata/ata_xpt.c		optional scbus
 cam/ata/ata_pmp.c		optional scbus
 cam/nvme/nvme_all.c		optional scbus
 cam/nvme/nvme_da.c		optional nda | da
 cam/nvme/nvme_xpt.c		optional scbus
 cam/scsi/scsi_xpt.c		optional scbus
 cam/scsi/scsi_all.c		optional scbus
 cam/scsi/scsi_cd.c		optional cd
 cam/scsi/scsi_ch.c		optional ch
 cam/ata/ata_da.c		optional ada | da
 cam/ctl/ctl.c			optional ctl
 cam/ctl/ctl_backend.c		optional ctl
 cam/ctl/ctl_backend_block.c	optional ctl
 cam/ctl/ctl_backend_ramdisk.c	optional ctl
 cam/ctl/ctl_cmd_table.c		optional ctl
 cam/ctl/ctl_frontend.c		optional ctl
 cam/ctl/ctl_frontend_cam_sim.c	optional ctl
 cam/ctl/ctl_frontend_ioctl.c	optional ctl
 cam/ctl/ctl_frontend_iscsi.c	optional ctl cfiscsi
 cam/ctl/ctl_ha.c		optional ctl
 cam/ctl/ctl_scsi_all.c		optional ctl
 cam/ctl/ctl_tpc.c		optional ctl
 cam/ctl/ctl_tpc_local.c		optional ctl
 cam/ctl/ctl_error.c		optional ctl
 cam/ctl/ctl_util.c		optional ctl
 cam/ctl/scsi_ctl.c		optional ctl
 cam/mmc/mmc_xpt.c		optional scbus mmccam
 cam/mmc/mmc_sim.c		optional scbus mmccam
 cam/mmc/mmc_sim_if.m		optional scbus mmccam
 cam/mmc/mmc_da.c		optional scbus mmccam da
 cam/scsi/scsi_da.c		optional da
 cam/scsi/scsi_pass.c		optional pass
 cam/scsi/scsi_pt.c		optional pt
 cam/scsi/scsi_sa.c		optional sa
 cam/scsi/scsi_enc.c		optional ses
 cam/scsi/scsi_enc_ses.c		optional ses
 cam/scsi/scsi_enc_safte.c	optional ses
 cam/scsi/scsi_sg.c		optional sg
 cam/scsi/scsi_targ_bh.c		optional targbh
 cam/scsi/scsi_target.c		optional targ
 cam/scsi/smp_all.c		optional scbus
 
 # shared between zfs and dtrace
 cddl/compat/opensolaris/kern/opensolaris.c		optional dtrace compile-with "${CDDL_C}"
 cddl/compat/opensolaris/kern/opensolaris_proc.c		optional zfs | dtrace compile-with "${CDDL_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_misc.c		optional zfs | dtrace compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_cmn_err.c		optional zfs | dtrace compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_taskq.c		optional zfs | dtrace compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_kmem.c		optional zfs | dtrace compile-with "${ZFS_C}"
 
 #zfs solaris portability layer
 contrib/openzfs/module/os/freebsd/spl/acl_common.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/callb.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/list.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_acl.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_dtrace.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_kstat.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_policy.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_procfs_list.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_string.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_sunddi.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_sysevent.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_uio.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_vfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_vm.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_zlib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/spl/spl_zone.c		optional zfs compile-with "${ZFS_C}"
 
 
 
 # zfs specific
 
 #zfs avl
 contrib/openzfs/module/avl/avl.c				optional zfs compile-with "${ZFS_C}"
 
 # zfs lua support
 contrib/openzfs/module/lua/lapi.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lauxlib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lbaselib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lcode.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lcompat.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lcorolib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lctype.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/ldebug.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/ldo.c			optional zfs compile-with "${ZFS_C} ${NO_WINFINITE_RECURSION}"
 contrib/openzfs/module/lua/lfunc.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lgc.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/llex.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lmem.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lobject.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lopcodes.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lparser.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lstate.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lstring.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lstrlib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/ltable.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/ltablib.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/ltm.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lvm.c			optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/lua/lzio.c			optional zfs compile-with "${ZFS_C}"
 
 # zfs nvpair support
 contrib/openzfs/module/nvpair/fnvpair.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/nvpair/nvpair.c		optional zfs compile-with "${ZFS_RPC_C} ${NO_WSTRINGOP_OVERREAD}"
 contrib/openzfs/module/nvpair/nvpair_alloc_fixed.c	optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/nvpair/nvpair_alloc_spl.c	optional zfs compile-with "${ZFS_C}"
 
 #zfs platform compatibility code
 contrib/openzfs/module/os/freebsd/zfs/abd_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/arc_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/crypto_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/dmu_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/event_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/hkdf.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/kmod_core.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/spa_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/sysctl_os.c		optional zfs compile-with "${ZFS_C}  -include $S/modules/zfs/zfs_config.h"
 contrib/openzfs/module/os/freebsd/zfs/vdev_file.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/vdev_label_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_debug.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_ioctl_compat.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_ioctl_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_vfsops.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zfs_znode.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zio_crypt.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/os/freebsd/zfs/zvol_os.c		optional zfs compile-with "${ZFS_C}"
 
 #zfs unicode support
 contrib/openzfs/module/unicode/uconv.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/unicode/u8_textprep.c		optional zfs compile-with "${ZFS_C}"
 
 #zfs checksums / zcommon
 contrib/openzfs/module/zcommon/cityhash.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfeature_common.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_comutil.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_deleg.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_fletcher.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_fletcher_superscalar.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_fletcher_superscalar4.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_namecheck.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zfs_prop.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zpool_prop.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zcommon/zprop_common.c		optional zfs compile-with "${ZFS_C}"
 
 # zfs edon-r hash support
 contrib/openzfs/module/icp/algs/edonr/edonr.c		optional zfs compile-with "${ZFS_C}"
 
 # zfs blake3 hash support
 contrib/openzfs/module/icp/algs/blake3/blake3.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/icp/algs/blake3/blake3_generic.c	optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/icp/algs/blake3/blake3_impl.c	optional zfs compile-with "${ZFS_C}"
 
 # zfs sha2 hash support
 contrib/openzfs/module/icp/algs/sha2/sha2_generic.c	optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/icp/algs/sha2/sha256_impl.c	optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/icp/algs/sha2/sha512_impl.c	optional zfs compile-with "${ZFS_C}"
 
 #zfs core common code
 contrib/openzfs/module/zfs/abd.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/aggsum.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/arc.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/blake3_zfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/blkptr.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/bplist.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/bpobj.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/bptree.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/brt.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/btree.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/bqueue.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dbuf.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dbuf_stats.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dataset_kstats.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/ddt.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/ddt_zap.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_diff.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_object.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_objset.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_recv.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_redact.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_send.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_traverse.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_tx.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dmu_zfetch.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dnode.c		optional zfs compile-with "${ZFS_C} ${NO_WUNUSED_BUT_SET_VARIABLE}" \
 	warning "kernel contains CDDL licensed ZFS filesystem"
 contrib/openzfs/module/zfs/dnode_sync.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_bookmark.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_crypt.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_dataset.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_deadlist.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_deleg.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_destroy.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_dir.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_pool.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_prop.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_scan.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_synctask.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/dsl_userhold.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/edonr_zfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/fm.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/gzip.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/lzjb.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/lz4.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/lz4_zfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/metaslab.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/mmp.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/multilist.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/objlist.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/pathname.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/range_tree.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/refcount.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/rrwlock.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/sa.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/sha2_zfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/skein_zfs.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_checkpoint.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_config.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_errlog.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_history.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_log_spacemap.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_misc.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/spa_stats.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/space_map.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/space_reftree.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/txg.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/uberblock.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/unique.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_draid.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_draid_rand.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_indirect.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_indirect_births.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_indirect_mapping.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_initialize.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_label.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_mirror.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_missing.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_queue.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_rebuild.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_removal.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_root.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/vdev_trim.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zap.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zap_leaf.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zap_micro.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp_get.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp_global.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp_iter.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp_set.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zcp_synctask.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfeature.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_byteswap.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_chksum.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_fm.c		optional zfs compile-with "${ZFS_C} ${NO_WUNUSED_BUT_SET_VARIABLE}"
 contrib/openzfs/module/zfs/zfs_fuid.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_impl.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_ioctl.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_log.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_onexit.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_quota.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_ratelimit.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_replay.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_rlock.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_sa.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zfs_vnops.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zstd/zfs_zstd.c		optional zfs zstdio compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zil.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zio.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zio_checksum.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zio_compress.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zio_inject.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zle.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zrlock.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zthr.c		optional zfs compile-with "${ZFS_C}"
 contrib/openzfs/module/zfs/zvol.c		optional zfs compile-with "${ZFS_C}"
 
 # dtrace specific
 cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c	optional dtrace compile-with "${DTRACE_C}" \
 							warning "kernel contains CDDL licensed DTRACE"
 cddl/contrib/opensolaris/uts/common/dtrace/dtrace_xoroshiro128_plus.c	optional dtrace compile-with "${DTRACE_C}"
 cddl/dev/dtmalloc/dtmalloc.c		optional dtmalloc        | dtraceall compile-with "${CDDL_C}"
 cddl/dev/profile/profile.c		optional dtrace_profile  | dtraceall compile-with "${CDDL_C}"
 cddl/dev/sdt/sdt.c			optional dtrace_sdt      | dtraceall compile-with "${CDDL_C}"
 cddl/dev/fbt/fbt.c			optional dtrace_fbt      | dtraceall compile-with "${FBT_C}"
 cddl/dev/systrace/systrace.c		optional dtrace_systrace | dtraceall compile-with "${CDDL_C}"
 cddl/dev/prototype.c			optional dtrace_prototype | dtraceall compile-with "${CDDL_C}"
 fs/nfsclient/nfs_clkdtrace.c		optional dtnfscl nfscl   | dtraceall nfscl compile-with "${CDDL_C}"
 compat/freebsd32/freebsd32_abort2.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_capability.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_ioctl.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_misc.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_syscalls.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_sysent.c	optional compat_freebsd32
 contrib/ck/src/ck_array.c				standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_barrier_centralized.c			standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_barrier_combining.c			standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_barrier_dissemination.c		standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_barrier_mcs.c				standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_barrier_tournament.c			standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_epoch.c				standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_hp.c					standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_hs.c					standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_ht.c					standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/ck/src/ck_rhs.c					standard compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 contrib/dev/acpica/common/ahids.c			optional acpi acpi_debug
 contrib/dev/acpica/common/ahuuids.c			optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbcmds.c		optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbconvert.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbdisply.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbexec.c		optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbhistry.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbinput.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbmethod.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbnames.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbobject.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbstats.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbtest.c		optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbutils.c	optional acpi acpi_debug
 contrib/dev/acpica/components/debugger/dbxface.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmbuffer.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmcstyle.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmdeferred.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmnames.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmopcode.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmresrc.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmresrcl.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmresrcl2.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmresrcs.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmutils.c	optional acpi acpi_debug
 contrib/dev/acpica/components/disassembler/dmwalk.c	optional acpi acpi_debug
 contrib/dev/acpica/components/dispatcher/dsargs.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dscontrol.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsdebug.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsfield.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsinit.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsmethod.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsmthdat.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsobject.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsopcode.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dspkginit.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dsutils.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dswexec.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dswload.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dswload2.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dswscope.c	optional acpi
 contrib/dev/acpica/components/dispatcher/dswstate.c	optional acpi
 contrib/dev/acpica/components/events/evevent.c		optional acpi
 contrib/dev/acpica/components/events/evglock.c		optional acpi
 contrib/dev/acpica/components/events/evgpe.c		optional acpi
 contrib/dev/acpica/components/events/evgpeblk.c		optional acpi
 contrib/dev/acpica/components/events/evgpeinit.c	optional acpi
 contrib/dev/acpica/components/events/evgpeutil.c	optional acpi
 contrib/dev/acpica/components/events/evhandler.c	optional acpi
 contrib/dev/acpica/components/events/evmisc.c		optional acpi
 contrib/dev/acpica/components/events/evregion.c		optional acpi
 contrib/dev/acpica/components/events/evrgnini.c		optional acpi
 contrib/dev/acpica/components/events/evsci.c		optional acpi
 contrib/dev/acpica/components/events/evxface.c		optional acpi
 contrib/dev/acpica/components/events/evxfevnt.c		optional acpi
 contrib/dev/acpica/components/events/evxfgpe.c		optional acpi
 contrib/dev/acpica/components/events/evxfregn.c		optional acpi
 contrib/dev/acpica/components/executer/exconcat.c	optional acpi
 contrib/dev/acpica/components/executer/exconfig.c	optional acpi
 contrib/dev/acpica/components/executer/exconvrt.c	optional acpi
 contrib/dev/acpica/components/executer/excreate.c	optional acpi
 contrib/dev/acpica/components/executer/exdebug.c	optional acpi
 contrib/dev/acpica/components/executer/exdump.c		optional acpi
 contrib/dev/acpica/components/executer/exfield.c	optional acpi
 contrib/dev/acpica/components/executer/exfldio.c	optional acpi
 contrib/dev/acpica/components/executer/exmisc.c		optional acpi
 contrib/dev/acpica/components/executer/exmutex.c	optional acpi
 contrib/dev/acpica/components/executer/exnames.c	optional acpi
 contrib/dev/acpica/components/executer/exoparg1.c	optional acpi
 contrib/dev/acpica/components/executer/exoparg2.c	optional acpi
 contrib/dev/acpica/components/executer/exoparg3.c	optional acpi
 contrib/dev/acpica/components/executer/exoparg6.c	optional acpi
 contrib/dev/acpica/components/executer/exprep.c		optional acpi
 contrib/dev/acpica/components/executer/exregion.c	optional acpi
 contrib/dev/acpica/components/executer/exresnte.c	optional acpi
 contrib/dev/acpica/components/executer/exresolv.c	optional acpi
 contrib/dev/acpica/components/executer/exresop.c	optional acpi
 contrib/dev/acpica/components/executer/exserial.c	optional acpi
 contrib/dev/acpica/components/executer/exstore.c	optional acpi
 contrib/dev/acpica/components/executer/exstoren.c	optional acpi
 contrib/dev/acpica/components/executer/exstorob.c	optional acpi
 contrib/dev/acpica/components/executer/exsystem.c	optional acpi
 contrib/dev/acpica/components/executer/extrace.c	optional acpi
 contrib/dev/acpica/components/executer/exutils.c	optional acpi
 contrib/dev/acpica/components/hardware/hwacpi.c		optional acpi
 contrib/dev/acpica/components/hardware/hwesleep.c	optional acpi
 contrib/dev/acpica/components/hardware/hwgpe.c		optional acpi
 contrib/dev/acpica/components/hardware/hwpci.c		optional acpi
 contrib/dev/acpica/components/hardware/hwregs.c		optional acpi
 contrib/dev/acpica/components/hardware/hwsleep.c	optional acpi
 contrib/dev/acpica/components/hardware/hwtimer.c	optional acpi
 contrib/dev/acpica/components/hardware/hwvalid.c	optional acpi
 contrib/dev/acpica/components/hardware/hwxface.c	optional acpi
 contrib/dev/acpica/components/hardware/hwxfsleep.c	optional acpi
 contrib/dev/acpica/components/namespace/nsaccess.c	optional acpi \
 	compile-with "${NORMAL_C} ${NO_WUNUSED_BUT_SET_VARIABLE}"
 contrib/dev/acpica/components/namespace/nsalloc.c	optional acpi
 contrib/dev/acpica/components/namespace/nsarguments.c	optional acpi
 contrib/dev/acpica/components/namespace/nsconvert.c	optional acpi
 contrib/dev/acpica/components/namespace/nsdump.c	optional acpi
 contrib/dev/acpica/components/namespace/nseval.c	optional acpi
 contrib/dev/acpica/components/namespace/nsinit.c	optional acpi
 contrib/dev/acpica/components/namespace/nsload.c	optional acpi
 contrib/dev/acpica/components/namespace/nsnames.c	optional acpi
 contrib/dev/acpica/components/namespace/nsobject.c	optional acpi
 contrib/dev/acpica/components/namespace/nsparse.c	optional acpi
 contrib/dev/acpica/components/namespace/nspredef.c	optional acpi
 contrib/dev/acpica/components/namespace/nsprepkg.c	optional acpi
 contrib/dev/acpica/components/namespace/nsrepair.c	optional acpi
 contrib/dev/acpica/components/namespace/nsrepair2.c	optional acpi
 contrib/dev/acpica/components/namespace/nssearch.c	optional acpi
 contrib/dev/acpica/components/namespace/nsutils.c	optional acpi
 contrib/dev/acpica/components/namespace/nswalk.c	optional acpi
 contrib/dev/acpica/components/namespace/nsxfeval.c	optional acpi
 contrib/dev/acpica/components/namespace/nsxfname.c	optional acpi
 contrib/dev/acpica/components/namespace/nsxfobj.c	optional acpi
 contrib/dev/acpica/components/parser/psargs.c		optional acpi
 contrib/dev/acpica/components/parser/psloop.c		optional acpi
 contrib/dev/acpica/components/parser/psobject.c		optional acpi
 contrib/dev/acpica/components/parser/psopcode.c		optional acpi
 contrib/dev/acpica/components/parser/psopinfo.c		optional acpi
 contrib/dev/acpica/components/parser/psparse.c		optional acpi
 contrib/dev/acpica/components/parser/psscope.c		optional acpi
 contrib/dev/acpica/components/parser/pstree.c		optional acpi
 contrib/dev/acpica/components/parser/psutils.c		optional acpi
 contrib/dev/acpica/components/parser/pswalk.c		optional acpi
 contrib/dev/acpica/components/parser/psxface.c		optional acpi
 contrib/dev/acpica/components/resources/rsaddr.c	optional acpi
 contrib/dev/acpica/components/resources/rscalc.c	optional acpi
 contrib/dev/acpica/components/resources/rscreate.c	optional acpi
 contrib/dev/acpica/components/resources/rsdump.c	optional acpi acpi_debug
 contrib/dev/acpica/components/resources/rsdumpinfo.c	optional acpi
 contrib/dev/acpica/components/resources/rsinfo.c	optional acpi
 contrib/dev/acpica/components/resources/rsio.c		optional acpi
 contrib/dev/acpica/components/resources/rsirq.c		optional acpi
 contrib/dev/acpica/components/resources/rslist.c	optional acpi
 contrib/dev/acpica/components/resources/rsmemory.c	optional acpi
 contrib/dev/acpica/components/resources/rsmisc.c	optional acpi
 contrib/dev/acpica/components/resources/rsserial.c	optional acpi
 contrib/dev/acpica/components/resources/rsutils.c	optional acpi
 contrib/dev/acpica/components/resources/rsxface.c	optional acpi
 contrib/dev/acpica/components/tables/tbdata.c		optional acpi
 contrib/dev/acpica/components/tables/tbfadt.c		optional acpi
 contrib/dev/acpica/components/tables/tbfind.c		optional acpi
 contrib/dev/acpica/components/tables/tbinstal.c		optional acpi
 contrib/dev/acpica/components/tables/tbprint.c		optional acpi
 contrib/dev/acpica/components/tables/tbutils.c		optional acpi
 contrib/dev/acpica/components/tables/tbxface.c		optional acpi
 contrib/dev/acpica/components/tables/tbxfload.c		optional acpi
 contrib/dev/acpica/components/tables/tbxfroot.c		optional acpi
 contrib/dev/acpica/components/utilities/utaddress.c	optional acpi
 contrib/dev/acpica/components/utilities/utalloc.c	optional acpi
 contrib/dev/acpica/components/utilities/utascii.c	optional acpi
 contrib/dev/acpica/components/utilities/utbuffer.c	optional acpi
 contrib/dev/acpica/components/utilities/utcache.c	optional acpi
 contrib/dev/acpica/components/utilities/utcksum.c	optional acpi
 contrib/dev/acpica/components/utilities/utcopy.c	optional acpi
 contrib/dev/acpica/components/utilities/utdebug.c	optional acpi
 contrib/dev/acpica/components/utilities/utdecode.c	optional acpi
 contrib/dev/acpica/components/utilities/utdelete.c	optional acpi
 contrib/dev/acpica/components/utilities/uterror.c	optional acpi
 contrib/dev/acpica/components/utilities/uteval.c	optional acpi
 contrib/dev/acpica/components/utilities/utexcep.c	optional acpi
 contrib/dev/acpica/components/utilities/utglobal.c	optional acpi
 contrib/dev/acpica/components/utilities/uthex.c		optional acpi
 contrib/dev/acpica/components/utilities/utids.c		optional acpi
 contrib/dev/acpica/components/utilities/utinit.c	optional acpi
 contrib/dev/acpica/components/utilities/utlock.c	optional acpi
 contrib/dev/acpica/components/utilities/utmath.c	optional acpi
 contrib/dev/acpica/components/utilities/utmisc.c	optional acpi
 contrib/dev/acpica/components/utilities/utmutex.c	optional acpi
 contrib/dev/acpica/components/utilities/utnonansi.c	optional acpi
 contrib/dev/acpica/components/utilities/utobject.c	optional acpi
 contrib/dev/acpica/components/utilities/utosi.c		optional acpi
 contrib/dev/acpica/components/utilities/utownerid.c	optional acpi
 contrib/dev/acpica/components/utilities/utpredef.c	optional acpi
 contrib/dev/acpica/components/utilities/utresdecode.c	optional acpi acpi_debug
 contrib/dev/acpica/components/utilities/utresrc.c	optional acpi
 contrib/dev/acpica/components/utilities/utstate.c	optional acpi
 contrib/dev/acpica/components/utilities/utstring.c	optional acpi
 contrib/dev/acpica/components/utilities/utstrsuppt.c	optional acpi
 contrib/dev/acpica/components/utilities/utstrtoul64.c	optional acpi
 contrib/dev/acpica/components/utilities/utuuid.c	optional acpi acpi_debug
 contrib/dev/acpica/components/utilities/utxface.c	optional acpi
 contrib/dev/acpica/components/utilities/utxferror.c	optional acpi
 contrib/dev/acpica/components/utilities/utxfinit.c	optional acpi
 contrib/dev/acpica/os_specific/service_layers/osgendbg.c	optional acpi acpi_debug
 netpfil/ipfilter/netinet/fil.c	optional ipfilter inet \
 	compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_auth.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_fil_freebsd.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_frag.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_log.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_nat.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_proxy.c optional ipfilter inet \
 	compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_state.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_lookup.c optional ipfilter inet \
 	compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -Wno-error -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_pool.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_htable.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter ${NO_WTAUTOLOGICAL_POINTER_COMPARE}"
 netpfil/ipfilter/netinet/ip_sync.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_nat6.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_rules.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_scan.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/ip_dstlist.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -Wno-unused -I$S/netpfil/ipfilter"
 netpfil/ipfilter/netinet/radix_ipf.c optional ipfilter inet \
 	compile-with "${NORMAL_C} -I$S/netpfil/ipfilter"
 contrib/libfdt/fdt.c		optional fdt
 contrib/libfdt/fdt_ro.c		optional fdt
 contrib/libfdt/fdt_rw.c		optional fdt
 contrib/libfdt/fdt_strerror.c	optional fdt
 contrib/libfdt/fdt_sw.c		optional fdt
 contrib/libfdt/fdt_wip.c	optional fdt
 contrib/libnv/cnvlist.c		standard
 contrib/libnv/dnvlist.c		standard
 contrib/libnv/nvlist.c		standard
 contrib/libnv/bsd_nvpair.c		standard
 # xz
 dev/xz/xz_mod.c	optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 contrib/xz-embedded/linux/lib/xz/xz_crc32.c	optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 contrib/xz-embedded/linux/lib/xz/xz_crc64.c	optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 contrib/xz-embedded/linux/lib/xz/xz_dec_bcj.c	optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 contrib/xz-embedded/linux/lib/xz/xz_dec_lzma2.c	optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 contrib/xz-embedded/linux/lib/xz/xz_dec_stream.c optional xz \
 	compile-with "${NORMAL_C} -DXZ_USE_CRC64 -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/"
 # Zstd
 contrib/zstd/lib/freebsd/zstd_kmalloc.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/common/zstd_common.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/common/fse_decompress.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/common/entropy_common.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/common/error_private.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/common/xxhash.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_compress.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_compress_literals.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_compress_sequences.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_compress_superblock.c	optional zstdio compile-with "${ZSTD_C} ${NO_WUNUSED_BUT_SET_VARIABLE}"
 contrib/zstd/lib/compress/fse_compress.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/hist.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/huf_compress.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_double_fast.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_fast.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_lazy.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_ldm.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/compress/zstd_opt.c		optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/decompress/zstd_ddict.c	optional zstdio compile-with ${ZSTD_C}
 contrib/zstd/lib/decompress/zstd_decompress.c	optional zstdio compile-with ${ZSTD_C}
 # See comment in sys/conf/kern.pre.mk
 contrib/zstd/lib/decompress/zstd_decompress_block.c	optional zstdio \
 	compile-with "${ZSTD_C} ${ZSTD_DECOMPRESS_BLOCK_FLAGS}"
 contrib/zstd/lib/decompress/huf_decompress.c	optional zstdio compile-with "${ZSTD_C} ${NO_WBITWISE_INSTEAD_OF_LOGICAL}"
 # Blake 2
 contrib/libb2/blake2b-ref.c	optional crypto | !random_loadable random_fenestrasx \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2 -Wno-cast-qual -DSUFFIX=_ref -Wno-unused-function"
 contrib/libb2/blake2s-ref.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2 -Wno-cast-qual -DSUFFIX=_ref -Wno-unused-function"
 crypto/blake2/blake2-sw.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2 -Wno-cast-qual"
 crypto/camellia/camellia.c	optional crypto
 crypto/camellia/camellia-api.c	optional crypto
 crypto/chacha20/chacha.c	standard
 crypto/chacha20/chacha-sw.c	optional crypto
 crypto/chacha20_poly1305.c	optional crypto
 crypto/curve25519.c		optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 crypto/des/des_ecb.c		optional netsmb
 crypto/des/des_setkey.c		optional netsmb
 crypto/openssl/ossl.c		optional ossl
 crypto/openssl/ossl_aes.c	optional ossl
 crypto/openssl/ossl_chacha20.c	optional ossl
 crypto/openssl/ossl_poly1305.c	optional ossl
 crypto/openssl/ossl_sha1.c	optional ossl
 crypto/openssl/ossl_sha256.c	optional ossl
 crypto/openssl/ossl_sha512.c	optional ossl
 crypto/rc4/rc4.c		optional netgraph_mppc_encryption
 crypto/rijndael/rijndael-alg-fst.c optional crypto | ekcd | geom_bde | \
 	!random_loadable | wlan_ccmp
 crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | !random_loadable
 crypto/rijndael/rijndael-api.c	optional crypto | wlan_ccmp
 crypto/sha1.c			optional carp | crypto | ether | \
 	netgraph_mppc_encryption | sctp
 crypto/sha2/sha256c.c		optional crypto | ekcd | geom_bde | \
 	!random_loadable | sctp | zfs
 crypto/sha2/sha512c.c		optional crypto | geom_bde | zfs
 crypto/skein/skein.c		optional crypto | zfs
 crypto/skein/skein_block.c	optional crypto | zfs
 crypto/siphash/siphash.c	optional inet | inet6 | wg
 crypto/siphash/siphash_test.c	optional inet | inet6 | wg
 ddb/db_access.c			optional ddb
 ddb/db_break.c			optional ddb
 ddb/db_capture.c		optional ddb
 ddb/db_command.c		optional ddb
 ddb/db_examine.c		optional ddb
 ddb/db_expr.c			optional ddb
 ddb/db_input.c			optional ddb
 ddb/db_lex.c			optional ddb
 ddb/db_main.c			optional ddb
 ddb/db_output.c			optional ddb
 ddb/db_print.c			optional ddb
 ddb/db_ps.c			optional ddb
 ddb/db_run.c			optional ddb
 ddb/db_script.c			optional ddb
 ddb/db_sym.c			optional ddb
 ddb/db_thread.c			optional ddb
 ddb/db_textdump.c		optional ddb
 ddb/db_variables.c		optional ddb
 ddb/db_watch.c			optional ddb
 ddb/db_write_cmd.c		optional ddb
 dev/aac/aac.c			optional aac
 dev/aac/aac_cam.c		optional aacp aac
 dev/aac/aac_debug.c		optional aac
 dev/aac/aac_disk.c		optional aac
 dev/aac/aac_pci.c		optional aac pci
 dev/aacraid/aacraid.c		optional aacraid
 dev/aacraid/aacraid_cam.c	optional aacraid scbus
 dev/aacraid/aacraid_debug.c	optional aacraid
 dev/aacraid/aacraid_pci.c	optional aacraid pci
 dev/acpi_support/acpi_wmi.c	optional acpi_wmi acpi
 dev/acpi_support/acpi_asus.c	optional acpi_asus acpi
 dev/acpi_support/acpi_asus_wmi.c	optional acpi_asus_wmi acpi
 dev/acpi_support/acpi_fujitsu.c	optional acpi_fujitsu acpi
 dev/acpi_support/acpi_hp.c	optional acpi_hp acpi
 dev/acpi_support/acpi_ibm.c	optional acpi_ibm acpi
 dev/acpi_support/acpi_panasonic.c optional acpi_panasonic acpi
 dev/acpi_support/acpi_sony.c	optional acpi_sony acpi
 dev/acpi_support/acpi_toshiba.c	optional acpi_toshiba acpi
 dev/acpi_support/atk0110.c	optional aibs acpi
 dev/acpica/Osd/OsdDebug.c	optional acpi
 dev/acpica/Osd/OsdHardware.c	optional acpi
 dev/acpica/Osd/OsdInterrupt.c	optional acpi
 dev/acpica/Osd/OsdMemory.c	optional acpi
 dev/acpica/Osd/OsdSchedule.c	optional acpi
 dev/acpica/Osd/OsdStream.c	optional acpi
 dev/acpica/Osd/OsdSynch.c	optional acpi
 dev/acpica/Osd/OsdTable.c	optional acpi
 dev/acpica/acpi.c		optional acpi
 dev/acpica/acpi_acad.c		optional acpi
 dev/acpica/acpi_apei.c		optional acpi
 dev/acpica/acpi_battery.c	optional acpi
 dev/acpica/acpi_button.c	optional acpi
 dev/acpica/acpi_cmbat.c		optional acpi
 dev/acpica/acpi_cpu.c		optional acpi
 dev/acpica/acpi_ec.c		optional acpi
 dev/acpica/acpi_ged.c		optional acpi_ged acpi
 dev/acpica/acpi_isab.c		optional acpi isa
 dev/acpica/acpi_lid.c		optional acpi
 dev/acpica/acpi_package.c	optional acpi
 dev/acpica/acpi_perf.c		optional acpi
 dev/acpica/acpi_powerres.c	optional acpi
 dev/acpica/acpi_quirk.c		optional acpi
 dev/acpica/acpi_resource.c	optional acpi
 dev/acpica/acpi_container.c	optional acpi
 dev/acpica/acpi_smbat.c		optional acpi
 dev/acpica/acpi_thermal.c	optional acpi
 dev/acpica/acpi_throttle.c	optional acpi
 dev/acpica/acpi_video.c		optional acpi_video acpi
 dev/acpica/acpi_dock.c		optional acpi_dock acpi
 dev/adlink/adlink.c		optional adlink
 dev/ae/if_ae.c			optional ae pci
 dev/age/if_age.c		optional age pci
 dev/agp/agp.c			optional agp pci
 dev/agp/agp_if.m		optional agp pci
 dev/ahci/ahci.c			optional ahci
 dev/ahci/ahciem.c		optional ahci
 dev/ahci/ahci_pci.c		optional ahci pci
 dev/aic7xxx/ahc_isa.c		optional ahc isa
 dev/aic7xxx/ahc_pci.c		optional ahc pci \
 	compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}"
 dev/aic7xxx/ahd_pci.c		optional ahd pci \
 	compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}"
 dev/aic7xxx/aic7770.c		optional ahc
 dev/aic7xxx/aic79xx.c		optional ahd pci
 dev/aic7xxx/aic79xx_osm.c	optional ahd pci
 dev/aic7xxx/aic79xx_pci.c	optional ahd pci
 dev/aic7xxx/aic79xx_reg_print.c	optional ahd pci ahd_reg_pretty_print
 dev/aic7xxx/aic7xxx.c		optional ahc
 dev/aic7xxx/aic7xxx_93cx6.c	optional ahc
 dev/aic7xxx/aic7xxx_osm.c	optional ahc
 dev/aic7xxx/aic7xxx_pci.c	optional ahc pci
 dev/aic7xxx/aic7xxx_reg_print.c	optional ahc ahc_reg_pretty_print
 dev/al_eth/al_eth.c				optional al_eth	fdt	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 dev/al_eth/al_init_eth_lm.c			optional al_eth	fdt	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 dev/al_eth/al_init_eth_kr.c			optional al_eth	fdt	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_iofic.c		optional al_iofic	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_serdes_25g.c		optional al_serdes	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_serdes_hssp.c		optional al_serdes	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_udma_config.c		optional al_udma	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_udma_debug.c		optional al_udma	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_udma_iofic.c		optional al_udma	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_hal_udma_main.c		optional al_udma	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/al_serdes.c			optional al_serdes	\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/eth/al_hal_eth_kr.c		optional al_eth		\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 contrib/alpine-hal/eth/al_hal_eth_main.c	optional al_eth		\
 	no-depend	\
 	compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${.IMPSRC}"
 dev/alc/if_alc.c		optional alc pci
 dev/ale/if_ale.c		optional ale pci
 dev/alpm/alpm.c			optional alpm pci
 dev/altera/avgen/altera_avgen.c		optional altera_avgen
 dev/altera/avgen/altera_avgen_fdt.c	optional altera_avgen fdt
 dev/altera/avgen/altera_avgen_nexus.c	optional altera_avgen
 dev/altera/msgdma/msgdma.c		optional altera_msgdma xdma
 dev/altera/sdcard/altera_sdcard.c	optional altera_sdcard
 dev/altera/sdcard/altera_sdcard_disk.c	optional altera_sdcard
 dev/altera/sdcard/altera_sdcard_io.c	optional altera_sdcard
 dev/altera/sdcard/altera_sdcard_fdt.c	optional altera_sdcard fdt
 dev/altera/sdcard/altera_sdcard_nexus.c	optional altera_sdcard
 dev/altera/softdma/softdma.c	optional altera_softdma xdma fdt
 dev/altera/pio/pio.c		optional altera_pio
 dev/altera/pio/pio_if.m		optional altera_pio
 dev/amdpm/amdpm.c		optional amdpm pci | nfpm pci
 dev/amdsmb/amdsmb.c		optional amdsmb pci
 #
 dev/ata/ata_if.m		optional ata | atacore
 dev/ata/ata-all.c		optional ata | atacore
 dev/ata/ata-dma.c		optional ata | atacore
 dev/ata/ata-lowlevel.c		optional ata | atacore
 dev/ata/ata-sata.c		optional ata | atacore
 dev/ata/ata-isa.c		optional ata isa | ataisa
 dev/ata/ata-pci.c		optional ata pci | atapci
 dev/ata/chipsets/ata-acard.c	optional ata pci | ataacard
 dev/ata/chipsets/ata-acerlabs.c	optional ata pci | ataacerlabs
 dev/ata/chipsets/ata-amd.c	optional ata pci | ataamd
 dev/ata/chipsets/ata-ati.c	optional ata pci | ataati
 dev/ata/chipsets/ata-cenatek.c	optional ata pci | atacenatek
 dev/ata/chipsets/ata-cypress.c	optional ata pci | atacypress
 dev/ata/chipsets/ata-cyrix.c	optional ata pci | atacyrix
 dev/ata/chipsets/ata-highpoint.c	optional ata pci | atahighpoint
 dev/ata/chipsets/ata-intel.c	optional ata pci | ataintel
 dev/ata/chipsets/ata-ite.c	optional ata pci | ataite
 dev/ata/chipsets/ata-jmicron.c	optional ata pci | atajmicron
 dev/ata/chipsets/ata-marvell.c	optional ata pci | atamarvell
 dev/ata/chipsets/ata-micron.c	optional ata pci | atamicron
 dev/ata/chipsets/ata-national.c	optional ata pci | atanational
 dev/ata/chipsets/ata-netcell.c	optional ata pci | atanetcell
 dev/ata/chipsets/ata-nvidia.c	optional ata pci | atanvidia
 dev/ata/chipsets/ata-promise.c	optional ata pci | atapromise
 dev/ata/chipsets/ata-serverworks.c	optional ata pci | ataserverworks
 dev/ata/chipsets/ata-siliconimage.c	optional ata pci | atasiliconimage | ataati
 dev/ata/chipsets/ata-sis.c	optional ata pci | atasis
 dev/ata/chipsets/ata-via.c	optional ata pci | atavia
 #
 dev/ath/if_ath.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_alq.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_beacon.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_btcoex.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_btcoex_mci.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_debug.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_descdma.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_keycache.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_ioctl.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_led.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_lna_div.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_pci.c		optional ath pci \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_tx.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_tx_edma.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_tx_ht.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_tdma.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_sysctl.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_rx.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_rx_edma.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/if_ath_spectral.c	optional ath \
 	compile-with "${ATH_C}"
 dev/ath/ah_osdep.c		optional ath \
 	compile-with "${ATH_C}"
 #
 dev/ath/ath_hal/ah.c		optional ath \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_eeprom_v1.c	optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_eeprom_v3.c	optional ath_hal | ath_ar5211 | ath_ar5212 \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_eeprom_v14.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_eeprom_v4k.c \
 	optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_eeprom_9287.c \
 	optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C}"
 dev/ath/ath_hal/ah_regdomain.c	optional ath \
 	compile-with "${ATH_C} ${NO_WSHIFT_COUNT_NEGATIVE} ${NO_WSHIFT_COUNT_OVERFLOW}"
 # ar5210
 dev/ath/ath_hal/ar5210/ar5210_attach.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_beacon.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_interrupts.c	optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_keycache.c	optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_misc.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_phy.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_power.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_recv.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_reset.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5210/ar5210_xmit.c		optional ath_hal | ath_ar5210 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar5211
 dev/ath/ath_hal/ar5211/ar5211_attach.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_beacon.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_interrupts.c	optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_keycache.c	optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_misc.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_phy.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_power.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_recv.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_reset.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5211/ar5211_xmit.c		optional ath_hal | ath_ar5211 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar5212
 dev/ath/ath_hal/ar5212/ar5212_ani.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_attach.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_beacon.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_eeprom.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_gpio.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_interrupts.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_keycache.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_misc.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_phy.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_power.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_recv.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_reset.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_rfgain.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5212_xmit.c \
 	optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \
 	ath_ar9285 ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar5416 (depends on ar5212)
 dev/ath/ath_hal/ar5416/ar5416_ani.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_attach.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_beacon.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_btcoex.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_cal.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_cal_iq.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_eeprom.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_gpio.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_interrupts.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_keycache.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_misc.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_phy.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_power.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_radar.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_recv.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_reset.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_spectral.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar5416_xmit.c \
 	optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
 	ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar9160 (depends on ar5416)
 dev/ath/ath_hal/ar9001/ar9160_attach.c optional ath_hal | ath_ar9160 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar9280 (depends on ar5416)
 dev/ath/ath_hal/ar9002/ar9280_attach.c optional ath_hal | ath_ar9280 | \
 	ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9280_olc.c optional ath_hal | ath_ar9280 | \
 	ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar9285 (depends on ar5416 and ar9280)
 dev/ath/ath_hal/ar9002/ar9285_attach.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285_btcoex.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285_reset.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285_cal.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285_phy.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285_diversity.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 # ar9287 (depends on ar5416)
 dev/ath/ath_hal/ar9002/ar9287_attach.c optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9287_reset.c optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9287_cal.c optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9287_olc.c optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 
 # ar9300
 contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal ${NO_WCONSTANT_CONVERSION}"
 contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_paprd.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_power.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_radar.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal ${NO_WSOMETIMES_UNINITIALIZED} -Wno-unused-function"
 contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_spectral.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c optional ath_hal | ath_ar9300 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal"
 
 # rf backends
 dev/ath/ath_hal/ar5212/ar2316.c	optional ath_rf2316 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar2317.c	optional ath_rf2317 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar2413.c	optional ath_hal | ath_rf2413 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar2425.c	optional ath_hal | ath_rf2425 | ath_rf2417 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5111.c	optional ath_hal | ath_rf5111 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5112.c	optional ath_hal | ath_rf5112 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5212/ar5413.c	optional ath_hal | ath_rf5413 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar5416/ar2133.c optional ath_hal | ath_ar5416 | \
 	ath_ar9130 | ath_ar9160 | ath_ar9280 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9280.c optional ath_hal | ath_ar9280 | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9285.c optional ath_hal | ath_ar9285 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 dev/ath/ath_hal/ar9002/ar9287.c optional ath_hal | ath_ar9287 \
 	compile-with "${ATH_C} -I$S/dev/ath/ath_hal"
 
 # ath rate control algorithms
 dev/ath/ath_rate/amrr/amrr.c	optional ath_rate_amrr \
 	compile-with "${ATH_C}"
 dev/ath/ath_rate/onoe/onoe.c	optional ath_rate_onoe \
 	compile-with "${ATH_C}"
 dev/ath/ath_rate/sample/sample.c	optional ath_rate_sample \
 	compile-with "${ATH_C}"
 # ath DFS modules
 dev/ath/ath_dfs/null/dfs_null.c	optional ath \
 	compile-with "${ATH_C}"
 #
 dev/backlight/backlight_if.m		optional backlight | compat_linuxkpi
 dev/backlight/backlight.c		optional backlight | compat_linuxkpi
 dev/bce/if_bce.c			optional bce
 dev/bfe/if_bfe.c			optional bfe
 dev/bge/if_bge.c			optional bge
 dev/bhnd/bhnd.c				optional bhnd
 dev/bhnd/bhnd_erom.c			optional bhnd
 dev/bhnd/bhnd_erom_if.m			optional bhnd
 dev/bhnd/bhnd_subr.c			optional bhnd
 dev/bhnd/bhnd_bus_if.m			optional bhnd
 dev/bhnd/bhndb/bhnd_bhndb.c		optional bhndb bhnd
 dev/bhnd/bhndb/bhndb.c			optional bhndb bhnd
 dev/bhnd/bhndb/bhndb_bus_if.m		optional bhndb bhnd
 dev/bhnd/bhndb/bhndb_hwdata.c		optional bhndb bhnd
 dev/bhnd/bhndb/bhndb_if.m		optional bhndb bhnd
 dev/bhnd/bhndb/bhndb_pci.c		optional bhndb_pci bhndb bhnd pci
 dev/bhnd/bhndb/bhndb_pci_hwdata.c 	optional bhndb_pci bhndb bhnd pci
 dev/bhnd/bhndb/bhndb_pci_sprom.c	optional bhndb_pci bhndb bhnd pci
 dev/bhnd/bhndb/bhndb_subr.c		optional bhndb bhnd
 dev/bhnd/bcma/bcma.c			optional bcma bhnd
 dev/bhnd/bcma/bcma_bhndb.c		optional bcma bhnd bhndb
 dev/bhnd/bcma/bcma_erom.c		optional bcma bhnd
 dev/bhnd/bcma/bcma_subr.c		optional bcma bhnd
 dev/bhnd/cores/chipc/bhnd_chipc_if.m	optional bhnd
 dev/bhnd/cores/chipc/bhnd_sprom_chipc.c	optional bhnd
 dev/bhnd/cores/chipc/bhnd_pmu_chipc.c	optional bhnd
 dev/bhnd/cores/chipc/chipc.c		optional bhnd
 dev/bhnd/cores/chipc/chipc_cfi.c	optional bhnd cfi 
 dev/bhnd/cores/chipc/chipc_gpio.c	optional bhnd gpio
 dev/bhnd/cores/chipc/chipc_slicer.c	optional bhnd cfi | bhnd spibus
 dev/bhnd/cores/chipc/chipc_spi.c	optional bhnd spibus
 dev/bhnd/cores/chipc/chipc_subr.c	optional bhnd
 dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c	optional bhnd
 dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_if.m	optional bhnd
 dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_hostb_if.m	optional bhnd
 dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c	optional bhnd
 dev/bhnd/cores/pci/bhnd_pci.c		optional bhnd pci
 dev/bhnd/cores/pci/bhnd_pci_hostb.c	optional bhndb bhnd pci
 dev/bhnd/cores/pci/bhnd_pcib.c		optional bhnd_pcib bhnd pci
 dev/bhnd/cores/pcie2/bhnd_pcie2.c	optional bhnd pci
 dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c	optional bhndb bhnd pci
 dev/bhnd/cores/pcie2/bhnd_pcie2b.c	optional bhnd_pcie2b bhnd pci
 dev/bhnd/cores/pmu/bhnd_pmu.c		optional bhnd
 dev/bhnd/cores/pmu/bhnd_pmu_core.c	optional bhnd
 dev/bhnd/cores/pmu/bhnd_pmu_if.m	optional bhnd
 dev/bhnd/cores/pmu/bhnd_pmu_subr.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_bcm.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_btxt.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_sprom.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_sprom_subr.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_data_tlv.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_if.m		optional bhnd
 dev/bhnd/nvram/bhnd_nvram_io.c		optional bhnd
 dev/bhnd/nvram/bhnd_nvram_iobuf.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_ioptr.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_iores.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_plist.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_store.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_store_subr.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_subr.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_value.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_value_fmts.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_value_prf.c	optional bhnd
 dev/bhnd/nvram/bhnd_nvram_value_subr.c	optional bhnd
 dev/bhnd/nvram/bhnd_sprom.c		optional bhnd
 dev/bhnd/siba/siba.c			optional siba bhnd
 dev/bhnd/siba/siba_bhndb.c		optional siba bhnd bhndb
 dev/bhnd/siba/siba_erom.c		optional siba bhnd
 dev/bhnd/siba/siba_subr.c		optional siba bhnd
 #
 dev/bnxt/bnxt_hwrm.c		optional bnxt iflib pci
 dev/bnxt/bnxt_mgmt.c		optional bnxt iflib pci
 dev/bnxt/bnxt_sysctl.c		optional bnxt iflib pci
 dev/bnxt/bnxt_txrx.c		optional bnxt iflib pci
 dev/bnxt/if_bnxt.c		optional bnxt iflib pci
 dev/bwi/bwimac.c		optional bwi
 dev/bwi/bwiphy.c		optional bwi
 dev/bwi/bwirf.c			optional bwi
 dev/bwi/if_bwi.c		optional bwi
 dev/bwi/if_bwi_pci.c		optional bwi pci
 dev/bwn/if_bwn.c		optional bwn bhnd
 dev/bwn/if_bwn_pci.c		optional bwn pci bhnd bhndb bhndb_pci
 dev/bwn/if_bwn_phy_common.c	optional bwn bhnd
 dev/bwn/if_bwn_phy_g.c		optional bwn bhnd
 dev/bwn/if_bwn_phy_lp.c		optional bwn bhnd
 dev/bwn/if_bwn_phy_n.c		optional bwn bhnd
 dev/bwn/if_bwn_util.c		optional bwn bhnd
 dev/cadence/if_cgem.c		optional cgem fdt
 dev/cardbus/card_if.m		standard
 dev/cardbus/cardbus.c		optional cardbus
 dev/cardbus/cardbus_cis.c	optional cardbus
 dev/cardbus/cardbus_device.c	optional cardbus
 dev/cardbus/power_if.m		standard
 dev/cas/if_cas.c		optional cas
 dev/cfi/cfi_bus_fdt.c		optional cfi fdt
 dev/cfi/cfi_bus_nexus.c		optional cfi
 dev/cfi/cfi_core.c		optional cfi
 dev/cfi/cfi_dev.c		optional cfi
 dev/cfi/cfi_disk.c		optional cfid
 dev/chromebook_platform/chromebook_platform.c	optional chromebook_platform
 dev/ciss/ciss.c			optional ciss
 dev/cpufreq/ichss.c		optional cpufreq pci
 dev/cxgb/cxgb_main.c		optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/cxgb_sge.c		optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_mc5.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_vsc7323.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_vsc8211.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_ael1002.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_aq100x.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_mv88e1xxx.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_xgmac.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_t3_hw.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/common/cxgb_tn1010.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/sys/uipc_mvec.c	optional cxgb pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgb/cxgb_t3fw.c		optional cxgb cxgb_t3fw \
 	compile-with "${NORMAL_C} -I$S/dev/cxgb"
 dev/cxgbe/t4_clip.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_filter.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_if.m		optional cxgbe pci
 dev/cxgbe/t4_iov.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_mp_ring.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_main.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_netmap.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_sched.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_sge.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_smt.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_l2t.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_tracer.c		optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/t4_vf.c		optional cxgbev pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/common/t4_hw.c	optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/common/t4vf_hw.c	optional cxgbev pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/crypto/t6_kern_tls.c	optional cxgbe pci kern_tls \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/crypto/t4_keyctx.c	optional cxgbe pci \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/cudbg_common.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/cudbg_flash_utils.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/cudbg_lib.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/cudbg_wtp.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/fastlz.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cxgbe/cudbg/fastlz_api.c	optional cxgbe \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 t4fw_cfg.c		optional cxgbe					\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk t4fw_cfg.fw:t4fw_cfg t4fw_cfg_uwire.fw:t4fw_cfg_uwire t4fw.fw:t4fw -mt4fw_cfg -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"t4fw_cfg.c"
 t4fw_cfg.fwo		optional cxgbe					\
 	dependency	"t4fw_cfg.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t4fw_cfg.fwo"
 t4fw_cfg.fw		optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t4fw_cfg.txt"		\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t4fw_cfg.fw"
 t4fw_cfg_uwire.fwo	optional cxgbe					\
 	dependency	"t4fw_cfg_uwire.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t4fw_cfg_uwire.fwo"
 t4fw_cfg_uwire.fw	optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t4fw_cfg_uwire.txt"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t4fw_cfg_uwire.fw"
 t4fw.fwo		optional cxgbe					\
 	dependency	"t4fw.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t4fw.fwo"
 t4fw.fw			optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t4fw-1.27.4.0.bin"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t4fw.fw"
 t5fw_cfg.c		optional cxgbe					\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk t5fw_cfg.fw:t5fw_cfg t5fw_cfg_uwire.fw:t5fw_cfg_uwire t5fw.fw:t5fw -mt5fw_cfg -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"t5fw_cfg.c"
 t5fw_cfg.fwo		optional cxgbe					\
 	dependency	"t5fw_cfg.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t5fw_cfg.fwo"
 t5fw_cfg.fw		optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t5fw_cfg.txt"		\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t5fw_cfg.fw"
 t5fw_cfg_uwire.fwo	optional cxgbe					\
 	dependency	"t5fw_cfg_uwire.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t5fw_cfg_uwire.fwo"
 t5fw_cfg_uwire.fw	optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t5fw_cfg_uwire.txt"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t5fw_cfg_uwire.fw"
 t5fw.fwo		optional cxgbe					\
 	dependency	"t5fw.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t5fw.fwo"
 t5fw.fw			optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t5fw-1.27.4.0.bin"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t5fw.fw"
 t6fw_cfg.c		optional cxgbe					\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk t6fw_cfg.fw:t6fw_cfg t6fw_cfg_uwire.fw:t6fw_cfg_uwire t6fw.fw:t6fw -mt6fw_cfg -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"t6fw_cfg.c"
 t6fw_cfg.fwo		optional cxgbe					\
 	dependency	"t6fw_cfg.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t6fw_cfg.fwo"
 t6fw_cfg.fw		optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t6fw_cfg.txt"		\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t6fw_cfg.fw"
 t6fw_cfg_uwire.fwo	optional cxgbe					\
 	dependency	"t6fw_cfg_uwire.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t6fw_cfg_uwire.fwo"
 t6fw_cfg_uwire.fw	optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t6fw_cfg_uwire.txt"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t6fw_cfg_uwire.fw"
 t6fw.fwo		optional cxgbe					\
 	dependency	"t6fw.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"t6fw.fwo"
 t6fw.fw			optional cxgbe					\
 	dependency	"$S/dev/cxgbe/firmware/t6fw-1.27.4.0.bin"	\
 	compile-with	"${CP} ${.ALLSRC} ${.TARGET}"			\
 	no-obj no-implicit-rule						\
 	clean		"t6fw.fw"
 dev/cxgbe/crypto/t4_crypto.c	optional ccr \
 	compile-with "${NORMAL_C} -I$S/dev/cxgbe"
 dev/cyapa/cyapa.c		optional cyapa iicbus
 dev/dc/if_dc.c			optional dc pci
 dev/dc/dcphy.c			optional dc pci
 dev/dc/pnphy.c			optional dc pci
 dev/dcons/dcons.c		optional dcons
 dev/dcons/dcons_crom.c		optional dcons_crom
 dev/dcons/dcons_os.c		optional dcons
 dev/dialog/da9063/da9063_if.m	optional da9063_pmic
 dev/dialog/da9063/da9063_iic.c	optional da9063_pmic iicbus fdt
 dev/dialog/da9063/da9063_rtc.c	optional da9063_rtc fdt
 dev/drm2/drm_agpsupport.c	optional drm2
 dev/drm2/drm_auth.c		optional drm2
 dev/drm2/drm_bufs.c		optional drm2
 dev/drm2/drm_buffer.c		optional drm2
 dev/drm2/drm_context.c		optional drm2
 dev/drm2/drm_crtc.c		optional drm2
 dev/drm2/drm_crtc_helper.c	optional drm2
 dev/drm2/drm_dma.c		optional drm2
 dev/drm2/drm_dp_helper.c	optional drm2
 dev/drm2/drm_dp_iic_helper.c	optional drm2
 dev/drm2/drm_drv.c		optional drm2
 dev/drm2/drm_edid.c		optional drm2
 dev/drm2/drm_fb_helper.c	optional drm2
 dev/drm2/drm_fops.c		optional drm2
 dev/drm2/drm_gem.c		optional drm2
 dev/drm2/drm_gem_names.c	optional drm2
 dev/drm2/drm_global.c		optional drm2
 dev/drm2/drm_hashtab.c		optional drm2
 dev/drm2/drm_ioctl.c		optional drm2
 dev/drm2/drm_irq.c		optional drm2
 dev/drm2/drm_linux_list_sort.c	optional drm2
 dev/drm2/drm_lock.c		optional drm2
 dev/drm2/drm_memory.c		optional drm2
 dev/drm2/drm_mm.c		optional drm2
 dev/drm2/drm_modes.c		optional drm2
 dev/drm2/drm_pci.c		optional drm2
 dev/drm2/drm_platform.c		optional drm2
 dev/drm2/drm_scatter.c		optional drm2
 dev/drm2/drm_stub.c		optional drm2
 dev/drm2/drm_sysctl.c		optional drm2
 dev/drm2/drm_vm.c		optional drm2
 dev/drm2/drm_os_freebsd.c	optional drm2
 dev/drm2/ttm/ttm_agp_backend.c	optional drm2
 dev/drm2/ttm/ttm_lock.c		optional drm2
 dev/drm2/ttm/ttm_object.c	optional drm2
 dev/drm2/ttm/ttm_tt.c		optional drm2
 dev/drm2/ttm/ttm_bo_util.c	optional drm2
 dev/drm2/ttm/ttm_bo.c		optional drm2
 dev/drm2/ttm/ttm_bo_manager.c	optional drm2
 dev/drm2/ttm/ttm_execbuf_util.c	optional drm2
 dev/drm2/ttm/ttm_memory.c	optional drm2
 dev/drm2/ttm/ttm_page_alloc.c	optional drm2
 dev/drm2/ttm/ttm_bo_vm.c	optional drm2
 dev/efidev/efidev.c		optional efirt
 dev/efidev/efirt.c		optional efirt
 dev/efidev/efirtc.c		optional efirt
 dev/e1000/if_em.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/em_txrx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/igb_txrx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_80003es2lan.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82540.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82541.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82542.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82543.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82571.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_82575.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_ich8lan.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_i210.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_api.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_base.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_mac.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_manage.c	optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_nvm.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_phy.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_vf.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_mbx.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/e1000/e1000_osdep.c		optional em \
 	compile-with "${NORMAL_C} -I$S/dev/e1000"
 dev/et/if_et.c			optional et
 dev/ena/ena.c			optional ena \
 	compile-with "${NORMAL_C} -I$S/contrib"
 dev/ena/ena_datapath.c		optional ena \
 	compile-with "${NORMAL_C} -I$S/contrib"
 dev/ena/ena_netmap.c		optional ena \
 	compile-with "${NORMAL_C} -I$S/contrib"
 dev/ena/ena_rss.c		optional ena \
 	compile-with "${NORMAL_C} -I$S/contrib"
 dev/ena/ena_sysctl.c 		optional ena \
 	compile-with "${NORMAL_C} -I$S/contrib"
 contrib/ena-com/ena_com.c	optional ena
 contrib/ena-com/ena_eth_com.c	optional ena
 dev/etherswitch/arswitch/arswitch.c		optional arswitch
 dev/etherswitch/arswitch/arswitch_reg.c		optional arswitch
 dev/etherswitch/arswitch/arswitch_phy.c		optional arswitch
 dev/etherswitch/arswitch/arswitch_8216.c	optional arswitch
 dev/etherswitch/arswitch/arswitch_8226.c	optional arswitch
 dev/etherswitch/arswitch/arswitch_8316.c	optional arswitch
 dev/etherswitch/arswitch/arswitch_8327.c	optional arswitch
 dev/etherswitch/arswitch/arswitch_vlans.c	optional arswitch
 dev/etherswitch/etherswitch.c		optional etherswitch
 dev/etherswitch/etherswitch_if.m	optional etherswitch
 dev/etherswitch/ip17x/ip17x.c		optional ip17x
 dev/etherswitch/ip17x/ip175c.c		optional ip17x
 dev/etherswitch/ip17x/ip175d.c		optional ip17x
 dev/etherswitch/ip17x/ip17x_phy.c	optional ip17x
 dev/etherswitch/ip17x/ip17x_vlans.c	optional ip17x
 dev/etherswitch/miiproxy.c		optional miiproxy
 dev/etherswitch/rtl8366/rtl8366rb.c	optional rtl8366rb
 dev/etherswitch/e6000sw/e6000sw.c	optional e6000sw fdt
 dev/etherswitch/e6000sw/e6060sw.c	optional e6060sw
 dev/etherswitch/infineon/adm6996fc.c	optional adm6996fc
 dev/etherswitch/micrel/ksz8995ma.c	optional ksz8995ma
 dev/etherswitch/ukswitch/ukswitch.c	optional ukswitch
 dev/evdev/cdev.c			optional evdev
 dev/evdev/evdev.c			optional evdev
 dev/evdev/evdev_mt.c			optional evdev
 dev/evdev/evdev_utils.c			optional evdev
 dev/evdev/uinput.c			optional evdev uinput
 dev/exca/exca.c			optional cbb
 dev/extres/clk/clk.c		optional clk
 dev/extres/clk/clkdev_if.m	optional clk
 dev/extres/clk/clknode_if.m	optional clk
 dev/extres/clk/clk_bus.c	optional clk fdt
 dev/extres/clk/clk_div.c	optional clk
 dev/extres/clk/clk_fixed.c	optional clk
 dev/extres/clk/clk_gate.c	optional clk
 dev/extres/clk/clk_link.c	optional clk
 dev/extres/clk/clk_mux.c	optional clk
 dev/extres/phy/phy.c		optional phy
 dev/extres/phy/phydev_if.m	optional phy fdt
 dev/extres/phy/phynode_if.m	optional phy
 dev/extres/phy/phy_usb.c	optional phy
 dev/extres/phy/phynode_usb_if.m	optional phy
 dev/extres/hwreset/hwreset.c	optional hwreset
 dev/extres/hwreset/hwreset_array.c	optional hwreset
 dev/extres/hwreset/hwreset_if.m	optional hwreset
 dev/extres/nvmem/nvmem.c	optional nvmem fdt
 dev/extres/nvmem/nvmem_if.m	optional nvmem
 dev/extres/regulator/regdev_if.m	optional regulator fdt
 dev/extres/regulator/regnode_if.m	optional regulator
 dev/extres/regulator/regulator.c	optional regulator
 dev/extres/regulator/regulator_bus.c	optional regulator fdt
 dev/extres/regulator/regulator_fixed.c	optional regulator
 dev/extres/syscon/syscon.c		optional syscon
 dev/extres/syscon/syscon_generic.c	optional syscon fdt
 dev/extres/syscon/syscon_if.m		optional syscon
 dev/extres/syscon/syscon_power.c	optional syscon syscon_power
 dev/fb/fbd.c			optional fbd | vt
 dev/fb/fb_if.m			standard
 dev/fb/splash.c			optional sc splash
 dev/fdt/fdt_clock.c		optional fdt fdt_clock
 dev/fdt/fdt_clock_if.m		optional fdt fdt_clock
 dev/fdt/fdt_common.c		optional fdt
 dev/fdt/fdt_pinctrl.c		optional fdt fdt_pinctrl
 dev/fdt/fdt_pinctrl_if.m	optional fdt fdt_pinctrl
 dev/fdt/fdt_slicer.c		optional fdt cfi | fdt mx25l | fdt n25q | fdt at45d
 dev/fdt/fdt_static_dtb.S	optional fdt fdt_dtb_static \
 	dependency	"${FDT_DTS_FILE:T:R}.dtb"
 dev/fdt/simplebus.c		optional fdt
 dev/fdt/simple_mfd.c		optional syscon fdt
 dev/filemon/filemon.c		optional filemon
 dev/firewire/firewire.c		optional firewire
 dev/firewire/fwcrom.c		optional firewire
 dev/firewire/fwdev.c		optional firewire
 dev/firewire/fwdma.c		optional firewire
 dev/firewire/fwmem.c		optional firewire
 dev/firewire/fwohci.c		optional firewire
 dev/firewire/fwohci_pci.c	optional firewire pci
 dev/firewire/if_fwe.c		optional fwe
 dev/firewire/if_fwip.c		optional fwip
 dev/firewire/sbp.c		optional sbp
 dev/firewire/sbp_targ.c		optional sbp_targ
 dev/flash/at45d.c		optional at45d
 dev/flash/cqspi.c		optional cqspi fdt xdma
 dev/flash/mx25l.c		optional mx25l
 dev/flash/n25q.c		optional n25q fdt
 dev/flash/qspi_if.m		optional cqspi fdt | n25q fdt
 dev/fxp/if_fxp.c		optional fxp
 dev/fxp/inphy.c			optional fxp
 dev/gem/if_gem.c		optional gem
 dev/gem/if_gem_pci.c		optional gem pci
 dev/gve/gve_adminq.c		optional gve
 dev/gve/gve_main.c		optional gve
 dev/gve/gve_qpl.c		optional gve
 dev/gve/gve_rx.c		optional gve
 dev/gve/gve_sysctl.c		optional gve
 dev/gve/gve_tx.c		optional gve
 dev/gve/gve_utils.c		optional gve
 dev/goldfish/goldfish_rtc.c	optional goldfish_rtc fdt
 dev/gpio/dwgpio/dwgpio.c	optional gpio dwgpio fdt
 dev/gpio/dwgpio/dwgpio_bus.c	optional gpio dwgpio fdt
 dev/gpio/dwgpio/dwgpio_if.m	optional gpio dwgpio fdt
 dev/gpio/gpiobacklight.c	optional gpiobacklight fdt
 dev/gpio/gpiokeys.c		optional gpiokeys fdt
 dev/gpio/gpiokeys_codes.c	optional gpiokeys fdt
 dev/gpio/gpiobus.c		optional gpio				\
 	dependency	"gpiobus_if.h"
 dev/gpio/gpioc.c		optional gpio				\
 	dependency	"gpio_if.h"
 dev/gpio/gpioiic.c		optional gpioiic
 dev/gpio/gpioled.c		optional gpioled !fdt
 dev/gpio/gpioled_fdt.c		optional gpioled fdt
 dev/gpio/gpiomdio.c		optional gpiomdio mii_bitbang
 dev/gpio/gpiopower.c		optional gpiopower fdt
 dev/gpio/gpioregulator.c	optional gpioregulator fdt
 dev/gpio/gpiospi.c		optional gpiospi
 dev/gpio/gpioths.c		optional gpioths
 dev/gpio/gpio_if.m		optional gpio
 dev/gpio/gpiobus_if.m		optional gpio
 dev/gpio/gpiopps.c		optional gpiopps fdt
 dev/gpio/ofw_gpiobus.c		optional fdt gpio
 dev/hid/bcm5974.c		optional bcm5974
 dev/hid/hconf.c			optional hconf
 dev/hid/hcons.c			optional hcons
 dev/hid/hgame.c			optional hgame
 dev/hid/hid.c			optional hid
 dev/hid/hid_if.m		optional hid
 dev/hid/hidbus.c		optional hidbus
 dev/hid/hidmap.c		optional hidmap
 dev/hid/hidquirk.c		optional hid
 dev/hid/hidraw.c		optional hidraw
 dev/hid/hkbd.c			optional hkbd
 dev/hid/hms.c			optional hms
 dev/hid/hmt.c			optional hmt hconf
 dev/hid/hpen.c			optional hpen
 dev/hid/hsctrl.c		optional hsctrl
 dev/hid/ietp.c			optional ietp
 dev/hid/ps4dshock.c		optional ps4dshock
 dev/hid/xb360gp.c		optional xb360gp
 dev/hifn/hifn7751.c		optional hifn
 dev/hptiop/hptiop.c		optional hptiop scbus
 dev/hwpmc/hwpmc_logging.c	optional hwpmc
 dev/hwpmc/hwpmc_mod.c		optional hwpmc
 dev/hwpmc/hwpmc_soft.c		optional hwpmc
 dev/ichiic/ig4_acpi.c		optional ig4 acpi iicbus
 dev/ichiic/ig4_iic.c		optional ig4 iicbus
 dev/ichiic/ig4_pci.c		optional ig4 pci iicbus
 dev/ichsmb/ichsmb.c		optional ichsmb
 dev/ichsmb/ichsmb_pci.c		optional ichsmb pci
 dev/ida/ida.c			optional ida
 dev/ida/ida_disk.c		optional ida
 dev/ida/ida_pci.c		optional ida pci
 dev/iicbus/acpi_iicbus.c	optional acpi iicbus | acpi compat_linuxkpi
 dev/iicbus/icee.c		optional icee
 dev/iicbus/if_ic.c		optional ic
 dev/iicbus/iic.c		optional iic
 dev/iicbus/iic_recover_bus.c	optional iicbus | compat_linuxkpi
 dev/iicbus/iicbb.c		optional iicbb | compat_linuxkpi
 dev/iicbus/iicbb_if.m		optional iicbb | compat_linuxkpi
 dev/iicbus/iicbus.c		optional iicbus | compat_linuxkpi
 dev/iicbus/iicbus_if.m		optional iicbus | compat_linuxkpi
 dev/iicbus/iichid.c		optional iichid acpi hid iicbus
 dev/iicbus/iiconf.c		optional iicbus | compat_linuxkpi
 dev/iicbus/iicsmb.c		optional iicsmb				\
 	dependency	"iicbus_if.h"
 dev/iicbus/adc/ad7418.c		optional ad7418
 dev/iicbus/adc/ads111x.c	optional ads111x
 dev/iicbus/adc/pcf8591.c	optional pcf8591
 dev/iicbus/controller/opencores/iicoc.c	optional iicoc
 dev/iicbus/controller/opencores/iicoc_fdt.c	optional iicoc fdt
 dev/iicbus/controller/opencores/iicoc_pci.c	optional iicoc pci
 dev/iicbus/mux/iicmux.c		optional iicmux
 dev/iicbus/mux/iicmux_if.m	optional iicmux
 dev/iicbus/mux/iic_gpiomux.c	optional iic_gpiomux fdt
 dev/iicbus/mux/ltc430x.c	optional ltc430x
 dev/iicbus/mux/pca954x.c	optional pca954x iicbus iicmux
 dev/iicbus/ofw_iicbus.c		optional fdt iicbus
 dev/iicbus/ofw_iicbus_if.m	optional fdt iicbus
 dev/iicbus/rtc/ds1307.c		optional ds1307
 dev/iicbus/rtc/ds13rtc.c	optional ds13rtc | ds133x | ds1374
 dev/iicbus/rtc/ds1672.c		optional ds1672
 dev/iicbus/rtc/ds3231.c		optional ds3231
 dev/iicbus/rtc/isl12xx.c	optional isl12xx
 dev/iicbus/rtc/nxprtc.c		optional nxprtc | pcf8563
 dev/iicbus/rtc/pcf85063.c	optional pcf85063 iicbus fdt
 dev/iicbus/rtc/rtc8583.c	optional rtc8583
 dev/iicbus/rtc/rv3032.c		optional rv3032 iicbus fdt
 dev/iicbus/rtc/rx8803.c		optional rx8803 iicbus fdt
 dev/iicbus/rtc/s35390a.c	optional s35390a
 dev/iicbus/sensor/htu21.c	optional htu21
 dev/iicbus/sensor/lm75.c	optional lm75
 dev/iicbus/sensor/max44009.c	optional max44009
 dev/iicbus/gpio/pcf8574.c	optional pcf8574
 dev/iicbus/gpio/tca64xx.c	optional tca64xx fdt gpio
 dev/iicbus/pmic/fan53555.c	optional fan53555 fdt | tcs4525 fdt
 dev/iicbus/pmic/silergy/sy8106a.c	optional sy8106a fdt
 dev/iicbus/pmic/silergy/syr827.c	optional syr827 fdt
 dev/igc/if_igc.c		optional igc iflib pci
 dev/igc/igc_api.c		optional igc iflib pci
 dev/igc/igc_base.c		optional igc iflib pci
 dev/igc/igc_i225.c		optional igc iflib pci
 dev/igc/igc_mac.c		optional igc iflib pci
 dev/igc/igc_nvm.c		optional igc iflib pci
 dev/igc/igc_phy.c		optional igc iflib pci
 dev/igc/igc_txrx.c		optional igc iflib pci
 dev/intpm/intpm.c		optional intpm pci
 # XXX Work around clang warning, until maintainer approves fix.
 dev/ips/ips.c			optional ips \
 	compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}"
 dev/ips/ips_commands.c		optional ips
 dev/ips/ips_disk.c		optional ips
 dev/ips/ips_ioctl.c		optional ips
 dev/ips/ips_pci.c		optional ips pci
 dev/ipw/if_ipw.c		optional ipw
 ipwbssfw.c			optional ipwbssfw | ipwfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk ipw_bss.fw:ipw_bss:130 -lintel_ipw -mipw_bss -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"ipwbssfw.c"
 ipw_bss.fwo			optional ipwbssfw | ipwfw		\
 	dependency	"ipw_bss.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"ipw_bss.fwo"
 ipw_bss.fw			optional ipwbssfw | ipwfw		\
 	dependency	"$S/contrib/dev/ipw/ipw2100-1.3.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"ipw_bss.fw"
 ipwibssfw.c			optional ipwibssfw | ipwfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk ipw_ibss.fw:ipw_ibss:130 -lintel_ipw -mipw_ibss -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"ipwibssfw.c"
 ipw_ibss.fwo			optional ipwibssfw | ipwfw		\
 	dependency	"ipw_ibss.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"ipw_ibss.fwo"
 ipw_ibss.fw			optional ipwibssfw | ipwfw		\
 	dependency	"$S/contrib/dev/ipw/ipw2100-1.3-i.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"ipw_ibss.fw"
 ipwmonitorfw.c			optional ipwmonitorfw | ipwfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk ipw_monitor.fw:ipw_monitor:130 -lintel_ipw -mipw_monitor -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"ipwmonitorfw.c"
 ipw_monitor.fwo			optional ipwmonitorfw | ipwfw		\
 	dependency	"ipw_monitor.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"ipw_monitor.fwo"
 ipw_monitor.fw			optional ipwmonitorfw | ipwfw		\
 	dependency	"$S/contrib/dev/ipw/ipw2100-1.3-p.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"ipw_monitor.fw"
 dev/iscsi/icl.c			optional iscsi
 dev/iscsi/icl_conn_if.m		optional cfiscsi | iscsi
 dev/iscsi/icl_soft.c		optional iscsi
 dev/iscsi/icl_soft_proxy.c	optional iscsi
 dev/iscsi/iscsi.c		optional iscsi scbus
 dev/ismt/ismt.c			optional ismt
 dev/isl/isl.c			optional isl iicbus
 dev/isp/isp.c			optional isp
 dev/isp/isp_freebsd.c		optional isp
 dev/isp/isp_library.c		optional isp
 dev/isp/isp_pci.c		optional isp pci
 dev/isp/isp_target.c		optional isp
 dev/ispfw/ispfw.c		optional ispfw
 dev/iwi/if_iwi.c		optional iwi
 iwibssfw.c			optional iwibssfw | iwifw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwi_bss.fw:iwi_bss:300 -lintel_iwi -miwi_bss -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwibssfw.c"
 iwi_bss.fwo			optional iwibssfw | iwifw		\
 	dependency	"iwi_bss.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwi_bss.fwo"
 iwi_bss.fw			optional iwibssfw | iwifw		\
 	dependency	"$S/contrib/dev/iwi/ipw2200-bss.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwi_bss.fw"
 iwiibssfw.c			optional iwiibssfw | iwifw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwi_ibss.fw:iwi_ibss:300 -lintel_iwi -miwi_ibss -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwiibssfw.c"
 iwi_ibss.fwo			optional iwiibssfw | iwifw		\
 	dependency	"iwi_ibss.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwi_ibss.fwo"
 iwi_ibss.fw			optional iwiibssfw | iwifw		\
 	dependency	"$S/contrib/dev/iwi/ipw2200-ibss.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwi_ibss.fw"
 iwimonitorfw.c			optional iwimonitorfw | iwifw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwi_monitor.fw:iwi_monitor:300 -lintel_iwi -miwi_monitor -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwimonitorfw.c"
 iwi_monitor.fwo			optional iwimonitorfw | iwifw		\
 	dependency	"iwi_monitor.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwi_monitor.fwo"
 iwi_monitor.fw			optional iwimonitorfw | iwifw		\
 	dependency	"$S/contrib/dev/iwi/ipw2200-sniffer.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwi_monitor.fw"
 dev/iwm/if_iwm.c		optional iwm
 dev/iwm/if_iwm_7000.c		optional iwm
 dev/iwm/if_iwm_8000.c		optional iwm
 dev/iwm/if_iwm_9000.c		optional iwm
 dev/iwm/if_iwm_9260.c		optional iwm
 dev/iwm/if_iwm_binding.c	optional iwm
 dev/iwm/if_iwm_fw.c		optional iwm
 dev/iwm/if_iwm_led.c		optional iwm
 dev/iwm/if_iwm_mac_ctxt.c	optional iwm
 dev/iwm/if_iwm_notif_wait.c	optional iwm
 dev/iwm/if_iwm_pcie_trans.c	optional iwm
 dev/iwm/if_iwm_phy_ctxt.c	optional iwm
 dev/iwm/if_iwm_phy_db.c		optional iwm
 dev/iwm/if_iwm_power.c		optional iwm
 dev/iwm/if_iwm_scan.c		optional iwm
 dev/iwm/if_iwm_sf.c		optional iwm
 dev/iwm/if_iwm_sta.c		optional iwm
 dev/iwm/if_iwm_time_event.c	optional iwm
 dev/iwm/if_iwm_util.c		optional iwm
 iwm3160fw.c			optional iwm3160fw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm3160.fw:iwm3160fw -miwm3160fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm3160fw.c"
 iwm3160fw.fwo			optional iwm3160fw | iwmfw		\
 	dependency	"iwm3160.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm3160fw.fwo"
 iwm3160.fw			optional iwm3160fw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-3160-17.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm3160.fw"
 iwm3168fw.c			optional iwm3168fw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm3168.fw:iwm3168fw -miwm3168fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm3168fw.c"
 iwm3168fw.fwo			optional iwm3168fw | iwmfw		\
 	dependency	"iwm3168.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm3168fw.fwo"
 iwm3168.fw			optional iwm3168fw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-3168-22.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm3168.fw"
 iwm7260fw.c			optional iwm7260fw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm7260.fw:iwm7260fw -miwm7260fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm7260fw.c"
 iwm7260fw.fwo			optional iwm7260fw | iwmfw		\
 	dependency	"iwm7260.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm7260fw.fwo"
 iwm7260.fw			optional iwm7260fw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-7260-17.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm7260.fw"
 iwm7265fw.c			optional iwm7265fw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm7265.fw:iwm7265fw -miwm7265fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm7265fw.c"
 iwm7265fw.fwo			optional iwm7265fw | iwmfw		\
 	dependency	"iwm7265.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm7265fw.fwo"
 iwm7265.fw			optional iwm7265fw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-7265-17.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm7265.fw"
 iwm7265Dfw.c			optional iwm7265Dfw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm7265D.fw:iwm7265Dfw -miwm7265Dfw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm7265Dfw.c"
 iwm7265Dfw.fwo			optional iwm7265Dfw | iwmfw		\
 	dependency	"iwm7265D.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm7265Dfw.fwo"
 iwm7265D.fw			optional iwm7265Dfw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-7265D-17.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm7265D.fw"
 iwm8000Cfw.c			optional iwm8000Cfw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm8000C.fw:iwm8000Cfw -miwm8000Cfw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm8000Cfw.c"
 iwm8000Cfw.fwo			optional iwm8000Cfw | iwmfw		\
 	dependency	"iwm8000C.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm8000Cfw.fwo"
 iwm8000C.fw			optional iwm8000Cfw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-8000C-16.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm8000C.fw"
 iwm8265.fw			optional iwm8265fw | iwmfw		\
 	dependency	"$S/contrib/dev/iwm/iwm-8265-22.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwm8265.fw"
 iwm8265fw.c			optional iwm8265fw | iwmfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwm8265.fw:iwm8265fw -miwm8265fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwm8265fw.c"
 iwm8265fw.fwo			optional iwm8265fw | iwmfw		\
 	dependency	"iwm8265.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwm8265fw.fwo"
 dev/iwn/if_iwn.c		optional iwn
 iwn1000fw.c			optional iwn1000fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn1000.fw:iwn1000fw -miwn1000fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn1000fw.c"
 iwn1000fw.fwo			optional iwn1000fw | iwnfw		\
 	dependency	"iwn1000.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn1000fw.fwo"
 iwn1000.fw			optional iwn1000fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-1000-39.31.5.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn1000.fw"
 iwn100fw.c			optional iwn100fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn100.fw:iwn100fw -miwn100fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn100fw.c"
 iwn100fw.fwo			optional iwn100fw | iwnfw		\
 	dependency	"iwn100.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn100fw.fwo"
 iwn100.fw			optional iwn100fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-100-39.31.5.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn100.fw"
 iwn105fw.c			optional iwn105fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn105.fw:iwn105fw -miwn105fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn105fw.c"
 iwn105fw.fwo			optional iwn105fw | iwnfw		\
 	dependency	"iwn105.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn105fw.fwo"
 iwn105.fw			optional iwn105fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-105-6-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn105.fw"
 iwn135fw.c			optional iwn135fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn135.fw:iwn135fw -miwn135fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn135fw.c"
 iwn135fw.fwo			optional iwn135fw | iwnfw		\
 	dependency	"iwn135.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn135fw.fwo"
 iwn135.fw			optional iwn135fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-135-6-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn135.fw"
 iwn2000fw.c			optional iwn2000fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn2000.fw:iwn2000fw -miwn2000fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn2000fw.c"
 iwn2000fw.fwo			optional iwn2000fw | iwnfw		\
 	dependency	"iwn2000.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn2000fw.fwo"
 iwn2000.fw			optional iwn2000fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-2000-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn2000.fw"
 iwn2030fw.c			optional iwn2030fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn2030.fw:iwn2030fw -miwn2030fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn2030fw.c"
 iwn2030fw.fwo			optional iwn2030fw | iwnfw		\
 	dependency	"iwn2030.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn2030fw.fwo"
 iwn2030.fw			optional iwn2030fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwnwifi-2030-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn2030.fw"
 iwn4965fw.c			optional iwn4965fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn4965.fw:iwn4965fw -miwn4965fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn4965fw.c"
 iwn4965fw.fwo			optional iwn4965fw | iwnfw		\
 	dependency	"iwn4965.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn4965fw.fwo"
 iwn4965.fw			optional iwn4965fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-4965-228.61.2.24.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn4965.fw"
 iwn5000fw.c			optional iwn5000fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn5000.fw:iwn5000fw -miwn5000fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn5000fw.c"
 iwn5000fw.fwo		optional iwn5000fw | iwnfw			\
 	dependency	"iwn5000.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn5000fw.fwo"
 iwn5000.fw			optional iwn5000fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-5000-8.83.5.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn5000.fw"
 iwn5150fw.c			optional iwn5150fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn5150.fw:iwn5150fw -miwn5150fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn5150fw.c"
 iwn5150fw.fwo			optional iwn5150fw | iwnfw		\
 	dependency	"iwn5150.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn5150fw.fwo"
 iwn5150.fw			optional iwn5150fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-5150-8.24.2.2.fw.uu"\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn5150.fw"
 iwn6000fw.c			optional iwn6000fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn6000.fw:iwn6000fw -miwn6000fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn6000fw.c"
 iwn6000fw.fwo			optional iwn6000fw | iwnfw		\
 	dependency	"iwn6000.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn6000fw.fwo"
 iwn6000.fw			optional iwn6000fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-6000-9.221.4.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn6000.fw"
 iwn6000g2afw.c			optional iwn6000g2afw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn6000g2a.fw:iwn6000g2afw -miwn6000g2afw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn6000g2afw.c"
 iwn6000g2afw.fwo		optional iwn6000g2afw | iwnfw		\
 	dependency	"iwn6000g2a.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn6000g2afw.fwo"
 iwn6000g2a.fw			optional iwn6000g2afw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-6000g2a-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn6000g2a.fw"
 iwn6000g2bfw.c			optional iwn6000g2bfw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn6000g2b.fw:iwn6000g2bfw -miwn6000g2bfw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn6000g2bfw.c"
 iwn6000g2bfw.fwo		optional iwn6000g2bfw | iwnfw		\
 	dependency	"iwn6000g2b.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn6000g2bfw.fwo"
 iwn6000g2b.fw			optional iwn6000g2bfw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-6000g2b-18.168.6.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn6000g2b.fw"
 iwn6050fw.c			optional iwn6050fw | iwnfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk iwn6050.fw:iwn6050fw -miwn6050fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"iwn6050fw.c"
 iwn6050fw.fwo			optional iwn6050fw | iwnfw		\
 	dependency	"iwn6050.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"iwn6050fw.fwo"
 iwn6050.fw			optional iwn6050fw | iwnfw		\
 	dependency	"$S/contrib/dev/iwn/iwlwifi-6050-41.28.5.1.fw.uu" \
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"iwn6050.fw"
 dev/ixgbe/if_ix.c		optional ix inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP"
 dev/ixgbe/if_ixv.c		optional ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP"
 dev/ixgbe/if_bypass.c		optional ix inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/if_fdir.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/if_sriov.c		optional ix inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ix_txrx.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_osdep.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_phy.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_api.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_common.c	optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_mbx.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_vf.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_82598.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_82599.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_x540.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_x550.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_dcb.c		optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_dcb_82598.c	optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_dcb_82599.c	optional ix inet | ixv inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/jedec_dimm/jedec_dimm.c	optional jedec_dimm smbus
 dev/jme/if_jme.c		optional jme pci
 dev/kbd/kbd.c			optional atkbd | pckbd | sc | ukbd | vt | hkbd
 dev/kbdmux/kbdmux.c		optional kbdmux
 dev/ksyms/ksyms.c		optional ksyms
 dev/le/am7990.c			optional le
 dev/le/am79900.c		optional le
 dev/le/if_le_pci.c		optional le pci
 dev/le/lance.c			optional le
 dev/led/led.c			standard
 dev/lge/if_lge.c		optional lge
 dev/liquidio/base/cn23xx_pf_device.c		optional lio	\
 	compile-with "${NORMAL_C}				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_console.c			optional lio	\
 	compile-with "${NORMAL_C}				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_ctrl.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_device.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_droq.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_mem_ops.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_request_manager.c		optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/base/lio_response_manager.c	optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_core.c				optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_ioctl.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_main.c				optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_rss.c				optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_rxtx.c				optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 dev/liquidio/lio_sysctl.c			optional lio	\
 	compile-with "${NORMAL_C} 				\
 	-I$S/dev/liquidio -I$S/dev/liquidio/base -DSMP"
 lio.c	optional lio						\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk lio_23xx_nic.bin.fw:lio_23xx_nic.bin -mlio_23xx_nic.bin -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local	\
 	clean		"lio.c"
 lio_23xx_nic.bin.fw.fwo optional lio				\
 	dependency	"lio_23xx_nic.bin.fw"			\
 	compile-with	"${NORMAL_FWO}"				\
 	no-implicit-rule					\
 	clean		"lio_23xx_nic.bin.fw.fwo"
 lio_23xx_nic.bin.fw	optional lio					\
 	dependency	"$S/contrib/dev/liquidio/lio_23xx_nic.bin.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"lio_23xx_nic.bin.fw"
 dev/malo/if_malo.c		optional malo
 dev/malo/if_malohal.c		optional malo
 dev/malo/if_malo_pci.c		optional malo pci
 dev/md/md.c			optional md
 dev/mdio/mdio_if.m		optional miiproxy | mdio
 dev/mdio/mdio.c			optional miiproxy | mdio
 dev/mem/memdev.c		optional mem
 dev/mem/memutil.c		optional mem
 dev/mfi/mfi.c			optional mfi
 dev/mfi/mfi_debug.c		optional mfi
 dev/mfi/mfi_pci.c		optional mfi pci
 dev/mfi/mfi_disk.c		optional mfi
 dev/mfi/mfi_syspd.c		optional mfi
 dev/mfi/mfi_tbolt.c		optional mfi
 dev/mfi/mfi_cam.c		optional mfip scbus
 dev/mii/acphy.c			optional miibus | acphy
 dev/mii/amphy.c			optional miibus | amphy
 dev/mii/atphy.c			optional miibus | atphy
 dev/mii/axphy.c			optional miibus | axphy
 dev/mii/bmtphy.c		optional miibus | bmtphy
 dev/mii/brgphy.c		optional miibus | brgphy
 dev/mii/ciphy.c			optional miibus | ciphy
 dev/mii/dp83822phy.c		optional miibus | dp83822phy
 dev/mii/dp83867phy.c		optional miibus | dp83867phy
 dev/mii/e1000phy.c		optional miibus | e1000phy
 dev/mii/gentbi.c		optional miibus | gentbi
 dev/mii/icsphy.c		optional miibus | icsphy
 dev/mii/ip1000phy.c		optional miibus | ip1000phy
 dev/mii/jmphy.c			optional miibus | jmphy
 dev/mii/lxtphy.c		optional miibus | lxtphy
 dev/mii/mcommphy.c		optional miibus | mcommphy
 dev/mii/micphy.c		optional miibus fdt | micphy fdt
 dev/mii/mii.c			optional miibus | mii
 dev/mii/mii_bitbang.c		optional miibus | mii_bitbang
 dev/mii/mii_physubr.c		optional miibus | mii
 dev/mii/mii_fdt.c		optional miibus fdt | mii fdt
 dev/mii/miibus_if.m		optional miibus | mii
 dev/mii/mv88e151x.c		optional miibus | mv88e151x
 dev/mii/nsgphy.c		optional miibus | nsgphy
 dev/mii/nsphy.c			optional miibus | nsphy
 dev/mii/nsphyter.c		optional miibus | nsphyter
 dev/mii/pnaphy.c		optional miibus | pnaphy
 dev/mii/qsphy.c			optional miibus | qsphy
 dev/mii/rdcphy.c		optional miibus | rdcphy
 dev/mii/rgephy.c		optional miibus | rgephy
 dev/mii/rlphy.c			optional miibus | rlphy
 dev/mii/rlswitch.c		optional rlswitch
 dev/mii/smcphy.c		optional miibus | smcphy
 dev/mii/smscphy.c		optional miibus | smscphy
 dev/mii/tdkphy.c		optional miibus | tdkphy
 dev/mii/truephy.c		optional miibus | truephy
 dev/mii/ukphy.c			optional miibus | mii
 dev/mii/ukphy_subr.c		optional miibus | mii
 dev/mii/vscphy.c		optional miibus | vscphy
 dev/mii/xmphy.c			optional miibus | xmphy
 dev/mlxfw/mlxfw_fsm.c			optional mlxfw \
 	compile-with "${MLXFW_C}"
 dev/mlxfw/mlxfw_mfa2.c			optional mlxfw \
 	compile-with "${MLXFW_C}"
 dev/mlxfw/mlxfw_mfa2_tlv_multi.c	optional mlxfw \
 	compile-with "${MLXFW_C}"
 dev/mlx/mlx.c			optional mlx
 dev/mlx/mlx_disk.c		optional mlx
 dev/mlx/mlx_pci.c		optional mlx pci
 dev/mmc/mmc_subr.c		optional mmc | mmcsd !mmccam
 dev/mmc/mmc.c			optional mmc !mmccam
 dev/mmc/mmcbr_if.m		standard
 dev/mmc/mmcbus_if.m		standard
 dev/mmc/mmcsd.c			optional mmcsd !mmccam
 dev/mmc/mmc_fdt_helpers.c	optional mmc regulator clk fdt | mmccam regulator clk fdt
 dev/mmc/mmc_helpers.c		optional mmc gpio regulator clk | mmccam gpio regulator clk
 dev/mmc/mmc_pwrseq.c		optional mmc clk regulator fdt | mmccam clk regulator fdt
 dev/mmc/mmc_pwrseq_if.m		optional mmc clk regulator fdt | mmccam clk regulator fdt
 dev/mmcnull/mmcnull.c		optional mmcnull
 dev/mpr/mpr.c			optional mpr
 dev/mpr/mpr_config.c		optional mpr
 # XXX Work around clang warning, until maintainer approves fix.
 dev/mpr/mpr_mapping.c		optional mpr \
 	compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}"
 dev/mpr/mpr_pci.c		optional mpr pci
 dev/mpr/mpr_sas.c		optional mpr \
 	compile-with "${NORMAL_C} ${NO_WUNNEEDED_INTERNAL_DECL}"
 dev/mpr/mpr_sas_lsi.c		optional mpr
 dev/mpr/mpr_table.c		optional mpr
 dev/mpr/mpr_user.c		optional mpr
 dev/mps/mps.c			optional mps
 dev/mps/mps_config.c		optional mps
 # XXX Work around clang warning, until maintainer approves fix.
 dev/mps/mps_mapping.c		optional mps \
 	compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}"
 dev/mps/mps_pci.c		optional mps pci
 dev/mps/mps_sas.c		optional mps \
 	compile-with "${NORMAL_C} ${NO_WUNNEEDED_INTERNAL_DECL}"
 dev/mps/mps_sas_lsi.c		optional mps
 dev/mps/mps_table.c		optional mps
 dev/mps/mps_user.c		optional mps
 dev/mpt/mpt.c			optional mpt
 dev/mpt/mpt_cam.c		optional mpt
 dev/mpt/mpt_debug.c		optional mpt
 dev/mpt/mpt_pci.c		optional mpt pci
 dev/mpt/mpt_raid.c		optional mpt
 dev/mpt/mpt_user.c		optional mpt
 dev/mrsas/mrsas.c		optional mrsas
 dev/mrsas/mrsas_cam.c		optional mrsas
 dev/mrsas/mrsas_ioctl.c		optional mrsas
 dev/mrsas/mrsas_fp.c		optional mrsas
 dev/msk/if_msk.c		optional msk
 dev/mvs/mvs.c			optional mvs
 dev/mvs/mvs_if.m		optional mvs
 dev/mvs/mvs_pci.c		optional mvs pci
 dev/mwl/if_mwl.c		optional mwl
 dev/mwl/if_mwl_pci.c		optional mwl pci
 dev/mwl/mwlhal.c		optional mwl
 mwlfw.c				optional mwlfw				\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk mw88W8363.fw:mw88W8363fw mwlboot.fw:mwlboot -mmwl -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"mwlfw.c"
 mw88W8363.fwo		optional mwlfw					\
 	dependency	"mw88W8363.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"mw88W8363.fwo"
 mw88W8363.fw		optional mwlfw					\
 	dependency	"$S/contrib/dev/mwl/mw88W8363.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"mw88W8363.fw"
 mwlboot.fwo		optional mwlfw					\
 	dependency	"mwlboot.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"mwlboot.fwo"
 mwlboot.fw		optional mwlfw					\
 	dependency	"$S/contrib/dev/mwl/mwlboot.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"mwlboot.fw"
 dev/mxge/if_mxge.c		optional mxge pci
 dev/mxge/mxge_eth_z8e.c		optional mxge pci
 dev/mxge/mxge_ethp_z8e.c	optional mxge pci
 dev/mxge/mxge_rss_eth_z8e.c	optional mxge pci
 dev/mxge/mxge_rss_ethp_z8e.c	optional mxge pci
 dev/my/if_my.c			optional my
 dev/netmap/if_ptnet.c		optional netmap inet
 dev/netmap/netmap.c		optional netmap
 dev/netmap/netmap_bdg.c		optional netmap
 dev/netmap/netmap_freebsd.c	optional netmap
 dev/netmap/netmap_generic.c	optional netmap
 dev/netmap/netmap_kloop.c	optional netmap
 dev/netmap/netmap_legacy.c	optional netmap
 dev/netmap/netmap_mbq.c		optional netmap
 dev/netmap/netmap_mem2.c	optional netmap
 dev/netmap/netmap_monitor.c	optional netmap
 dev/netmap/netmap_null.c	optional netmap
 dev/netmap/netmap_offloadings.c	optional netmap
 dev/netmap/netmap_pipe.c	optional netmap
 dev/netmap/netmap_vale.c	optional netmap
 # compile-with "${NORMAL_C} -Wconversion -Wextra"
 dev/nfsmb/nfsmb.c		optional nfsmb pci
 dev/nge/if_nge.c		optional nge
 dev/nmdm/nmdm.c			optional nmdm
 dev/null/null.c			standard
 dev/nvd/nvd.c			optional nvd nvme
 dev/nvme/nvme.c			optional nvme
 dev/nvme/nvme_ahci.c		optional nvme ahci
 dev/nvme/nvme_ctrlr.c		optional nvme
 dev/nvme/nvme_ctrlr_cmd.c	optional nvme
 dev/nvme/nvme_ns.c		optional nvme
 dev/nvme/nvme_ns_cmd.c		optional nvme
 dev/nvme/nvme_pci.c		optional nvme pci
 dev/nvme/nvme_qpair.c		optional nvme
 dev/nvme/nvme_sim.c		optional nvme scbus
 dev/nvme/nvme_sysctl.c		optional nvme
 dev/nvme/nvme_test.c		optional nvme
 dev/nvme/nvme_util.c		optional nvme
 dev/oce/oce_hw.c		optional oce pci
 dev/oce/oce_if.c		optional oce pci
 dev/oce/oce_mbox.c		optional oce pci
 dev/oce/oce_queue.c		optional oce pci
 dev/oce/oce_sysctl.c		optional oce pci
 dev/oce/oce_util.c		optional oce pci
 dev/ocs_fc/ocs_gendump.c	optional ocs_fc pci
 dev/ocs_fc/ocs_pci.c		optional ocs_fc pci
 dev/ocs_fc/ocs_ioctl.c		optional ocs_fc pci
 dev/ocs_fc/ocs_os.c		optional ocs_fc pci
 dev/ocs_fc/ocs_utils.c		optional ocs_fc pci
 dev/ocs_fc/ocs_hw.c		optional ocs_fc pci
 dev/ocs_fc/ocs_hw_queues.c	optional ocs_fc pci
 dev/ocs_fc/sli4.c		optional ocs_fc pci
 dev/ocs_fc/ocs_sm.c		optional ocs_fc pci
 dev/ocs_fc/ocs_device.c		optional ocs_fc pci
 dev/ocs_fc/ocs_xport.c		optional ocs_fc pci
 dev/ocs_fc/ocs_domain.c		optional ocs_fc pci
 dev/ocs_fc/ocs_sport.c		optional ocs_fc pci
 dev/ocs_fc/ocs_els.c		optional ocs_fc pci
 dev/ocs_fc/ocs_fabric.c		optional ocs_fc pci
 dev/ocs_fc/ocs_io.c		optional ocs_fc pci
 dev/ocs_fc/ocs_node.c		optional ocs_fc pci
 dev/ocs_fc/ocs_scsi.c		optional ocs_fc pci
 dev/ocs_fc/ocs_unsol.c		optional ocs_fc pci
 dev/ocs_fc/ocs_ddump.c		optional ocs_fc pci
 dev/ocs_fc/ocs_mgmt.c		optional ocs_fc pci
 dev/ocs_fc/ocs_cam.c		optional ocs_fc pci
 dev/ofw/ofw_bus_if.m		optional fdt
 dev/ofw/ofw_bus_subr.c		optional fdt
 dev/ofw/ofw_cpu.c		optional fdt
 dev/ofw/ofw_fdt.c		optional fdt
 dev/ofw/ofw_firmware.c		optional fdt
 dev/ofw/ofw_if.m		optional fdt
 dev/ofw/ofw_graph.c		optional fdt
 dev/ofw/ofw_subr.c		optional fdt
 dev/ofw/ofwbus.c		optional fdt
 dev/ofw/openfirm.c		optional fdt
 dev/ofw/openfirmio.c		optional fdt
 dev/ow/ow.c			optional ow				\
 	dependency	"owll_if.h"					\
 	dependency	"own_if.h"
 dev/ow/owll_if.m		optional ow
 dev/ow/own_if.m			optional ow
 dev/ow/ow_temp.c		optional ow_temp
 dev/ow/owc_gpiobus.c		optional owc gpio
 dev/pbio/pbio.c			optional pbio isa
 dev/pccbb/pccbb.c		optional cbb
 dev/pccbb/pccbb_pci.c		optional cbb pci
 dev/pcf/pcf.c			optional pcf
 dev/pci/fixup_pci.c		optional pci
 dev/pci/hostb_pci.c		optional pci
 dev/pci/ignore_pci.c		optional pci
 dev/pci/isa_pci.c		optional pci isa
 dev/pci/pci.c			optional pci
 dev/pci/pci_if.m		standard
 dev/pci/pci_iov.c		optional pci pci_iov
 dev/pci/pci_iov_if.m		standard
 dev/pci/pci_iov_schema.c	optional pci pci_iov
 dev/pci/pci_pci.c		optional pci
 dev/pci/pci_subr.c		optional pci
 dev/pci/pci_user.c		optional pci
 dev/pci/pcib_if.m		standard
 dev/pci/pcib_support.c		standard
 dev/pci/vga_pci.c		optional pci
 dev/pms/freebsd/driver/ini/src/agtiapi.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sadisc.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/mpi.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/saframe.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sahw.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sainit.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/saint.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sampicmd.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sampirsp.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/saphy.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/saport.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sasata.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sasmp.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sassp.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/satimer.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/sautil.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/saioctlcmd.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sallsdk/spc/mpidebug.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dminit.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dmsmp.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dmdisc.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dmport.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dmtimer.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/discovery/dm/dmmisc.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/sminit.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/smmisc.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/smsat.c				optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/smsatcb.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/smsathw.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/sat/src/smtimer.c			optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdinit.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdmisc.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdesgl.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdport.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdint.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdioctl.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdhw.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/ossacmnapi.c	optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tddmcmnapi.c	optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdsmcmnapi.c	optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/common/tdtimers.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sas/ini/itdio.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sas/ini/itdcb.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sas/ini/itdinit.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sas/ini/itddisc.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sata/host/sat.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sata/host/ossasat.c	optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/pms/RefTisa/tisa/sassata/sata/host/sathw.c		optional pmspcv \
 	compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w"
 dev/ppbus/if_plip.c		optional plip
 dev/ppbus/lpbb.c		optional lpbb
 dev/ppbus/lpt.c			optional lpt
 dev/ppbus/pcfclock.c		optional pcfclock
 dev/ppbus/ppb_1284.c		optional ppbus
 dev/ppbus/ppb_base.c		optional ppbus
 dev/ppbus/ppb_msq.c		optional ppbus
 dev/ppbus/ppbconf.c		optional ppbus
 dev/ppbus/ppbus_if.m		optional ppbus
 dev/ppbus/ppi.c			optional ppi
 dev/ppbus/pps.c			optional pps
 dev/ppc/ppc.c			optional ppc
 dev/ppc/ppc_acpi.c		optional ppc acpi
 dev/ppc/ppc_isa.c		optional ppc isa
 dev/ppc/ppc_pci.c		optional ppc pci
 dev/ppc/ppc_puc.c		optional ppc puc
 dev/proto/proto_bus_isa.c	optional proto acpi | proto isa
 dev/proto/proto_bus_pci.c	optional proto pci
 dev/proto/proto_busdma.c	optional proto
 dev/proto/proto_core.c		optional proto
 dev/pst/pst-iop.c		optional pst
 dev/pst/pst-pci.c		optional pst pci
 dev/pst/pst-raid.c		optional pst
 dev/pty/pty.c			optional pty
 dev/puc/puc.c			optional puc
 dev/puc/puc_cfg.c		optional puc
 dev/puc/puc_pci.c		optional puc pci
 dev/pwm/pwmc.c			optional pwm | pwmc
 dev/pwm/pwmbus.c		optional pwm | pwmbus
 dev/pwm/pwmbus_if.m		optional pwm | pwmbus
 dev/pwm/ofw_pwm.c		optional pwm fdt | pwmbus fdt
 dev/pwm/ofw_pwmbus.c		optional pwm fdt | pwmbus fdt
 dev/pwm/pwm_backlight.c		optional pwm pwm_backlight fdt
 dev/quicc/quicc_core.c		optional quicc
 dev/ral/rt2560.c		optional ral
 dev/ral/rt2661.c		optional ral
 dev/ral/rt2860.c		optional ral
 dev/ral/if_ral_pci.c		optional ral pci
 rt2561fw.c			optional rt2561fw | ralfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rt2561.fw:rt2561fw -mrt2561 -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rt2561fw.c"
 rt2561fw.fwo			optional rt2561fw | ralfw		\
 	dependency	"rt2561.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rt2561fw.fwo"
 rt2561.fw			optional rt2561fw | ralfw		\
 	dependency	"$S/contrib/dev/ral/rt2561.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rt2561.fw"
 rt2561sfw.c			optional rt2561sfw | ralfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rt2561s.fw:rt2561sfw -mrt2561s -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rt2561sfw.c"
 rt2561sfw.fwo			optional rt2561sfw | ralfw		\
 	dependency	"rt2561s.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rt2561sfw.fwo"
 rt2561s.fw			optional rt2561sfw | ralfw		\
 	dependency	"$S/contrib/dev/ral/rt2561s.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rt2561s.fw"
 rt2661fw.c			optional rt2661fw | ralfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rt2661.fw:rt2661fw -mrt2661 -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rt2661fw.c"
 rt2661fw.fwo			optional rt2661fw | ralfw		\
 	dependency	"rt2661.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rt2661fw.fwo"
 rt2661.fw			optional rt2661fw | ralfw		\
 	dependency	"$S/contrib/dev/ral/rt2661.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rt2661.fw"
 rt2860fw.c			optional rt2860fw | ralfw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rt2860.fw:rt2860fw -mrt2860 -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rt2860fw.c"
 rt2860fw.fwo			optional rt2860fw | ralfw		\
 	dependency	"rt2860.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rt2860fw.fwo"
 rt2860.fw			optional rt2860fw | ralfw		\
 	dependency	"$S/contrib/dev/ral/rt2860.fw.uu"		\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rt2860.fw"
 dev/random/random_infra.c	standard
 dev/random/random_harvestq.c	standard
 dev/random/randomdev.c		optional !random_loadable
 dev/random/fenestrasX/fx_brng.c	optional !random_loadable random_fenestrasx
 dev/random/fenestrasX/fx_main.c	optional !random_loadable random_fenestrasx \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2"
 dev/random/fenestrasX/fx_pool.c	optional !random_loadable random_fenestrasx \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2"
 dev/random/fenestrasX/fx_rng.c	optional !random_loadable random_fenestrasx \
 	compile-with "${NORMAL_C} -I$S/crypto/blake2"
 dev/random/fortuna.c		optional !random_loadable !random_fenestrasx
 dev/random/hash.c		optional !random_loadable
 dev/rccgpio/rccgpio.c		optional rccgpio gpio
 dev/re/if_re.c			optional re
 dev/rl/if_rl.c			optional rl pci
 dev/rndtest/rndtest.c		optional rndtest
 #
 dev/rtsx/rtsx.c			optional rtsx pci
 #
 dev/rtwn/if_rtwn.c		optional rtwn
 dev/rtwn/if_rtwn_beacon.c	optional rtwn
 dev/rtwn/if_rtwn_calib.c	optional rtwn
 dev/rtwn/if_rtwn_cam.c		optional rtwn
 dev/rtwn/if_rtwn_efuse.c	optional rtwn
 dev/rtwn/if_rtwn_fw.c		optional rtwn
 dev/rtwn/if_rtwn_rx.c		optional rtwn
 dev/rtwn/if_rtwn_task.c		optional rtwn
 dev/rtwn/if_rtwn_tx.c		optional rtwn
 #
 dev/rtwn/pci/rtwn_pci_attach.c	optional rtwn_pci pci
 dev/rtwn/pci/rtwn_pci_reg.c	optional rtwn_pci pci
 dev/rtwn/pci/rtwn_pci_rx.c	optional rtwn_pci pci
 dev/rtwn/pci/rtwn_pci_tx.c	optional rtwn_pci pci
 #
 dev/rtwn/usb/rtwn_usb_attach.c	optional rtwn_usb
 dev/rtwn/usb/rtwn_usb_ep.c	optional rtwn_usb
 dev/rtwn/usb/rtwn_usb_reg.c	optional rtwn_usb
 dev/rtwn/usb/rtwn_usb_rx.c	optional rtwn_usb
 dev/rtwn/usb/rtwn_usb_tx.c	optional rtwn_usb
 # RTL8188E
 dev/rtwn/rtl8188e/r88e_beacon.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_calib.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_chan.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_fw.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_init.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_led.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_tx.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_rf.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_rom.c	optional rtwn
 dev/rtwn/rtl8188e/r88e_rx.c	optional rtwn
 dev/rtwn/rtl8188e/pci/r88ee_attach.c	optional rtwn_pci pci
 dev/rtwn/rtl8188e/pci/r88ee_init.c	optional rtwn_pci pci
 dev/rtwn/rtl8188e/pci/r88ee_rx.c	optional rtwn_pci pci
 dev/rtwn/rtl8188e/usb/r88eu_attach.c	optional rtwn_usb
 dev/rtwn/rtl8188e/usb/r88eu_init.c	optional rtwn_usb
 # RTL8192C
 dev/rtwn/rtl8192c/r92c_attach.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_beacon.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_calib.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_chan.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_fw.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_init.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_llt.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_rf.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_rom.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_rx.c	optional rtwn
 dev/rtwn/rtl8192c/r92c_tx.c	optional rtwn
 dev/rtwn/rtl8192c/pci/r92ce_attach.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_calib.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_fw.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_init.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_led.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_rx.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/pci/r92ce_tx.c	optional rtwn_pci pci
 dev/rtwn/rtl8192c/usb/r92cu_attach.c	optional rtwn_usb
 dev/rtwn/rtl8192c/usb/r92cu_init.c	optional rtwn_usb
 dev/rtwn/rtl8192c/usb/r92cu_led.c	optional rtwn_usb
 dev/rtwn/rtl8192c/usb/r92cu_rx.c	optional rtwn_usb
 dev/rtwn/rtl8192c/usb/r92cu_tx.c	optional rtwn_usb
 # RTL8192E
 dev/rtwn/rtl8192e/r92e_chan.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_fw.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_init.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_led.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_rf.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_rom.c	optional rtwn
 dev/rtwn/rtl8192e/r92e_rx.c	optional rtwn
 dev/rtwn/rtl8192e/usb/r92eu_attach.c	optional rtwn_usb
 dev/rtwn/rtl8192e/usb/r92eu_init.c	optional rtwn_usb
 # RTL8812A
 dev/rtwn/rtl8812a/r12a_beacon.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_calib.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_caps.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_chan.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_fw.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_init.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_led.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_rf.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_rom.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_rx.c	optional rtwn
 dev/rtwn/rtl8812a/r12a_tx.c	optional rtwn
 dev/rtwn/rtl8812a/usb/r12au_attach.c	optional rtwn_usb
 dev/rtwn/rtl8812a/usb/r12au_init.c	optional rtwn_usb
 dev/rtwn/rtl8812a/usb/r12au_rx.c	optional rtwn_usb
 dev/rtwn/rtl8812a/usb/r12au_tx.c	optional rtwn_usb
 # RTL8821A
 dev/rtwn/rtl8821a/r21a_beacon.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_calib.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_chan.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_fw.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_init.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_led.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_rom.c	optional rtwn
 dev/rtwn/rtl8821a/r21a_rx.c	optional rtwn
 dev/rtwn/rtl8821a/usb/r21au_attach.c	optional rtwn_usb
 dev/rtwn/rtl8821a/usb/r21au_dfs.c	optional rtwn_usb
 dev/rtwn/rtl8821a/usb/r21au_init.c	optional rtwn_usb
 rtwn-rtl8188eefw.c		optional rtwn-rtl8188eefw | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8188eefw.fw:rtwn-rtl8188eefw:111 -mrtwn-rtl8188eefw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8188eefw.c"
 rtwn-rtl8188eefw.fwo		optional rtwn-rtl8188eefw | rtwnfw	\
 	dependency	"rtwn-rtl8188eefw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8188eefw.fwo"
 rtwn-rtl8188eefw.fw		optional rtwn-rtl8188eefw | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8188eefw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8188eefw.fw"
 rtwn-rtl8188eufw.c		optional rtwn-rtl8188eufw | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8188eufw.fw:rtwn-rtl8188eufw:111 -mrtwn-rtl8188eufw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8188eufw.c"
 rtwn-rtl8188eufw.fwo		optional rtwn-rtl8188eufw | rtwnfw	\
 	dependency	"rtwn-rtl8188eufw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8188eufw.fwo"
 rtwn-rtl8188eufw.fw		optional rtwn-rtl8188eufw | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8188eufw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8188eufw.fw"
 rtwn-rtl8192cfwE.c		optional rtwn-rtl8192cfwE | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE.fw:rtwn-rtl8192cfwE:111 -mrtwn-rtl8192cfwE -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8192cfwE.c"
 rtwn-rtl8192cfwE.fwo		optional rtwn-rtl8192cfwE | rtwnfw	\
 	dependency	"rtwn-rtl8192cfwE.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwE.fwo"
 rtwn-rtl8192cfwE.fw		optional rtwn-rtl8192cfwE | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8192cfwE.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwE.fw"
 rtwn-rtl8192cfwE_B.c		optional rtwn-rtl8192cfwE_B | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE_B.fw:rtwn-rtl8192cfwE_B:111 -mrtwn-rtl8192cfwE_B -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8192cfwE_B.c"
 rtwn-rtl8192cfwE_B.fwo		optional rtwn-rtl8192cfwE_B | rtwnfw	\
 	dependency	"rtwn-rtl8192cfwE_B.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwE_B.fwo"
 rtwn-rtl8192cfwE_B.fw		optional rtwn-rtl8192cfwE_B | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8192cfwE_B.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwE_B.fw"
 rtwn-rtl8192cfwT.c		optional rtwn-rtl8192cfwT | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwT.fw:rtwn-rtl8192cfwT:111 -mrtwn-rtl8192cfwT -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8192cfwT.c"
 rtwn-rtl8192cfwT.fwo		optional rtwn-rtl8192cfwT | rtwnfw	\
 	dependency	"rtwn-rtl8192cfwT.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwT.fwo"
 rtwn-rtl8192cfwT.fw		optional rtwn-rtl8192cfwT | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8192cfwT.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwT.fw"
 rtwn-rtl8192cfwU.c		optional rtwn-rtl8192cfwU | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwU.fw:rtwn-rtl8192cfwU:111 -mrtwn-rtl8192cfwU -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8192cfwU.c"
 rtwn-rtl8192cfwU.fwo		optional rtwn-rtl8192cfwU | rtwnfw	\
 	dependency	"rtwn-rtl8192cfwU.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwU.fwo"
 rtwn-rtl8192cfwU.fw		optional rtwn-rtl8192cfwU | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8192cfwU.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8192cfwU.fw"
 rtwn-rtl8192eufw.c		optional rtwn-rtl8192eufw | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192eufw.fw:rtwn-rtl8192eufw:111 -mrtwn-rtl8192eufw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8192eufw.c"
 rtwn-rtl8192eufw.fwo		optional rtwn-rtl8192eufw | rtwnfw	\
 	dependency	"rtwn-rtl8192eufw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8192eufw.fwo"
 rtwn-rtl8192eufw.fw		optional rtwn-rtl8192eufw | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8192eufw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8192eufw.fw"
 rtwn-rtl8812aufw.c		optional rtwn-rtl8812aufw | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8812aufw.fw:rtwn-rtl8812aufw:111 -mrtwn-rtl8812aufw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8812aufw.c"
 rtwn-rtl8812aufw.fwo		optional rtwn-rtl8812aufw | rtwnfw	\
 	dependency	"rtwn-rtl8812aufw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8812aufw.fwo"
 rtwn-rtl8812aufw.fw		optional rtwn-rtl8812aufw | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8812aufw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8812aufw.fw"
 rtwn-rtl8821aufw.c		optional rtwn-rtl8821aufw | rtwnfw	\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8821aufw.fw:rtwn-rtl8821aufw:111 -mrtwn-rtl8821aufw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rtwn-rtl8821aufw.c"
 rtwn-rtl8821aufw.fwo		optional rtwn-rtl8821aufw | rtwnfw	\
 	dependency	"rtwn-rtl8821aufw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rtwn-rtl8821aufw.fwo"
 rtwn-rtl8821aufw.fw		optional rtwn-rtl8821aufw | rtwnfw	\
 	dependency	"$S/contrib/dev/rtwn/rtwn-rtl8821aufw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rtwn-rtl8821aufw.fw"
 dev/safe/safe.c			optional safe
 dev/scc/scc_if.m		optional scc
 dev/scc/scc_bfe_quicc.c		optional scc quicc
 dev/scc/scc_core.c		optional scc
 dev/scc/scc_dev_quicc.c		optional scc quicc
 dev/scc/scc_dev_z8530.c		optional scc
 dev/sdhci/sdhci.c		optional sdhci
 dev/sdhci/sdhci_fdt.c		optional sdhci fdt regulator clk
 dev/sdhci/sdhci_fdt_gpio.c	optional sdhci fdt gpio
 dev/sdhci/sdhci_fsl_fdt.c	optional sdhci fdt gpio regulator clk
 dev/sdhci/sdhci_if.m		optional sdhci
 dev/sdhci/sdhci_acpi.c		optional sdhci acpi
 dev/sdhci/sdhci_pci.c		optional sdhci pci
 dev/sdio/sdio_if.m		optional mmccam
 dev/sdio/sdio_subr.c		optional mmccam
 dev/sdio/sdiob.c		optional mmccam
 dev/sff/sff_if.m		optional sff
 dev/sff/sfp_fdt.c		optional sff fdt
 dev/sge/if_sge.c		optional sge pci
 dev/siis/siis.c			optional siis pci
 dev/sis/if_sis.c		optional sis pci
 dev/sk/if_sk.c			optional sk pci
 dev/smbios/smbios.c		optional smbios
 dev/smbus/smb.c			optional smb
 dev/smbus/smbconf.c		optional smbus
 dev/smbus/smbus.c		optional smbus
 dev/smbus/smbus_if.m		optional smbus
 dev/smc/if_smc.c		optional smc
 dev/smc/if_smc_acpi.c		optional smc acpi
 dev/smc/if_smc_fdt.c		optional smc fdt
 dev/snp/snp.c			optional snp
 dev/sound/clone.c		optional sound
 dev/sound/unit.c		optional sound
 dev/sound/pci/als4000.c		optional snd_als4000 pci
 dev/sound/pci/atiixp.c		optional snd_atiixp pci
 dev/sound/pci/cmi.c		optional snd_cmi pci
 dev/sound/pci/cs4281.c		optional snd_cs4281 pci
 dev/sound/pci/csa.c		optional snd_csa pci
 dev/sound/pci/csapcm.c		optional snd_csa pci
 dev/sound/pci/emu10k1.c		optional snd_emu10k1 pci
 dev/sound/pci/emu10kx.c		optional snd_emu10kx pci
 dev/sound/pci/emu10kx-pcm.c	optional snd_emu10kx pci
 dev/sound/pci/emu10kx-midi.c	optional snd_emu10kx pci
 dev/sound/pci/envy24.c		optional snd_envy24 pci
 dev/sound/pci/envy24ht.c	optional snd_envy24ht pci
 dev/sound/pci/es137x.c		optional snd_es137x pci
 dev/sound/pci/fm801.c		optional snd_fm801 pci
 dev/sound/pci/ich.c		optional snd_ich pci
 dev/sound/pci/maestro3.c	optional snd_maestro3 pci
 dev/sound/pci/neomagic.c	optional snd_neomagic pci
 dev/sound/pci/solo.c		optional snd_solo pci
 dev/sound/pci/spicds.c		optional snd_spicds pci
 dev/sound/pci/t4dwave.c		optional snd_t4dwave pci
 dev/sound/pci/via8233.c		optional snd_via8233 pci
 dev/sound/pci/via82c686.c	optional snd_via82c686 pci
 dev/sound/pci/vibes.c		optional snd_vibes pci
 dev/sound/pci/hda/hdaa.c	optional snd_hda pci
 dev/sound/pci/hda/hdaa_patches.c	optional snd_hda pci
 dev/sound/pci/hda/hdac.c	optional snd_hda pci
 dev/sound/pci/hda/hdac_if.m	optional snd_hda pci
 dev/sound/pci/hda/hdacc.c	optional snd_hda pci
 dev/sound/pci/hdspe.c		optional snd_hdspe pci
 dev/sound/pci/hdspe-pcm.c	optional snd_hdspe pci
 dev/sound/pcm/ac97.c		optional sound
 dev/sound/pcm/ac97_if.m		optional sound
 dev/sound/pcm/ac97_patch.c	optional sound
 dev/sound/pcm/buffer.c		optional sound	\
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/channel.c		optional sound
 dev/sound/pcm/channel_if.m	optional sound
 dev/sound/pcm/dsp.c		optional sound
 dev/sound/pcm/feeder.c		optional sound
 dev/sound/pcm/feeder_chain.c	optional sound
 dev/sound/pcm/feeder_eq.c	optional sound	\
 	dependency	"feeder_eq_gen.h"	\
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/feeder_if.m	optional sound
 dev/sound/pcm/feeder_format.c	optional sound  \
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/feeder_matrix.c	optional sound  \
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/feeder_mixer.c	optional sound  \
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/feeder_rate.c	optional sound	\
 	dependency	"feeder_rate_gen.h"	\
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/feeder_volume.c	optional sound  \
 	dependency	"snd_fxdiv_gen.h"
 dev/sound/pcm/mixer.c		optional sound
 dev/sound/pcm/mixer_if.m	optional sound
 dev/sound/pcm/sndstat.c		optional sound
 dev/sound/pcm/sound.c		optional sound
 dev/sound/pcm/vchan.c		optional sound
 dev/sound/usb/uaudio.c		optional snd_uaudio usb
 dev/sound/usb/uaudio_pcm.c	optional snd_uaudio usb
 dev/sound/midi/midi.c		optional sound
 dev/sound/midi/mpu401.c		optional sound
 dev/sound/midi/mpu_if.m		optional sound
 dev/sound/midi/mpufoi_if.m	optional sound
 dev/sound/midi/sequencer.c	optional sound
 dev/sound/midi/synth_if.m	optional sound
 dev/spibus/acpi_spibus.c	optional acpi spibus
 dev/spibus/ofw_spibus.c		optional fdt spibus
 dev/spibus/spibus.c		optional spibus				\
 	dependency	"spibus_if.h"
 dev/spibus/spigen.c		optional spigen
 dev/spibus/spibus_if.m		optional spibus
 dev/ste/if_ste.c		optional ste pci
 dev/stge/if_stge.c		optional stge
 dev/sym/sym_hipd.c		optional sym				\
 	dependency	"$S/dev/sym/sym_{conf,defs}.h"
 dev/syscons/blank/blank_saver.c	optional blank_saver
 dev/syscons/daemon/daemon_saver.c optional daemon_saver
 dev/syscons/dragon/dragon_saver.c optional dragon_saver
 dev/syscons/fade/fade_saver.c	optional fade_saver
 dev/syscons/fire/fire_saver.c	optional fire_saver
 dev/syscons/green/green_saver.c	optional green_saver
 dev/syscons/logo/logo.c		optional logo_saver
 dev/syscons/logo/logo_saver.c	optional logo_saver
 dev/syscons/rain/rain_saver.c	optional rain_saver
 dev/syscons/schistory.c		optional sc
 dev/syscons/scmouse.c		optional sc
 dev/syscons/scterm.c		optional sc
 dev/syscons/scterm-dumb.c	optional sc !SC_NO_TERM_DUMB
 dev/syscons/scterm-sc.c		optional sc !SC_NO_TERM_SC
 dev/syscons/scterm-teken.c	optional sc !SC_NO_TERM_TEKEN
 dev/syscons/scvidctl.c		optional sc
 dev/syscons/scvtb.c		optional sc
 dev/syscons/snake/snake_saver.c	optional snake_saver
 dev/syscons/star/star_saver.c	optional star_saver
 dev/syscons/syscons.c		optional sc
 dev/syscons/sysmouse.c		optional sc
 dev/syscons/warp/warp_saver.c	optional warp_saver
 dev/tcp_log/tcp_log_dev.c	optional tcp_blackbox inet | tcp_blackbox inet6
 dev/tdfx/tdfx_pci.c		optional tdfx pci
 dev/ti/if_ti.c			optional ti pci
 dev/tws/tws.c			optional tws
 dev/tws/tws_cam.c		optional tws
 dev/tws/tws_hdm.c		optional tws
 dev/tws/tws_services.c		optional tws
 dev/tws/tws_user.c		optional tws
 dev/uart/uart_bus_acpi.c	optional uart acpi
 dev/uart/uart_bus_fdt.c		optional uart fdt
 dev/uart/uart_bus_isa.c		optional uart isa
 dev/uart/uart_bus_pci.c		optional uart pci
 dev/uart/uart_bus_puc.c		optional uart puc
 dev/uart/uart_bus_scc.c		optional uart scc
 dev/uart/uart_core.c		optional uart
 dev/uart/uart_cpu_acpi.c	optional uart acpi
 dev/uart/uart_dbg.c		optional uart gdb
 dev/uart/uart_dev_imx.c		optional uart uart_imx fdt
 dev/uart/uart_dev_msm.c		optional uart uart_msm fdt
 dev/uart/uart_dev_mvebu.c	optional uart uart_mvebu fdt
 dev/uart/uart_dev_ns8250.c	optional uart uart_ns8250 | uart uart_snps
 dev/uart/uart_dev_pl011.c	optional uart pl011
 dev/uart/uart_dev_quicc.c	optional uart quicc
 dev/uart/uart_dev_snps.c	optional uart uart_snps fdt
 dev/uart/uart_dev_z8530.c	optional uart uart_z8530 | uart scc
 dev/uart/uart_if.m		optional uart
 dev/uart/uart_subr.c		optional uart
 dev/uart/uart_tty.c		optional uart
 #
 # USB controller drivers
 #
 dev/usb/controller/musb_otg.c		optional musb
 dev/usb/controller/dwc_otg.c		optional dwcotg
 dev/usb/controller/dwc_otg_fdt.c	optional dwcotg fdt
 dev/usb/controller/dwc_otg_acpi.c	optional dwcotg acpi
 dev/usb/controller/ehci.c		optional ehci
 dev/usb/controller/ehci_msm.c		optional ehci_msm fdt
 dev/usb/controller/ehci_pci.c		optional ehci pci
 dev/usb/controller/ohci.c		optional ohci
 dev/usb/controller/ohci_pci.c		optional ohci pci
 dev/usb/controller/uhci.c		optional uhci
 dev/usb/controller/uhci_pci.c		optional uhci pci
 dev/usb/controller/xhci.c		optional xhci
 dev/usb/controller/xhci_pci.c		optional xhci pci
 dev/usb/controller/saf1761_otg.c	optional saf1761otg
 dev/usb/controller/saf1761_otg_fdt.c	optional saf1761otg fdt
 dev/usb/controller/uss820dci.c		optional uss820dci
 dev/usb/controller/usb_controller.c	optional usb
 #
 # USB storage drivers
 #
 dev/usb/storage/cfumass.c	optional cfumass ctl
 dev/usb/storage/umass.c		optional umass
 dev/usb/storage/urio.c		optional urio
 dev/usb/storage/ustorage_fs.c	optional usfs
 #
 # USB core
 #
 dev/usb/usb_busdma.c		optional usb
 dev/usb/usb_core.c		optional usb
 dev/usb/usb_debug.c		optional usb
 dev/usb/usb_dev.c		optional usb
 dev/usb/usb_device.c		optional usb
 dev/usb/usb_dynamic.c		optional usb
 dev/usb/usb_error.c		optional usb
 dev/usb/usb_fdt_support.c	optional usb fdt
 dev/usb/usb_generic.c		optional usb
 dev/usb/usb_handle_request.c	optional usb
 dev/usb/usb_hid.c		optional usb
 dev/usb/usb_hub.c		optional usb
 dev/usb/usb_hub_acpi.c		optional uacpi acpi
 dev/usb/usb_if.m		optional usb
 dev/usb/usb_lookup.c		optional usb
 dev/usb/usb_mbuf.c		optional usb
 dev/usb/usb_msctest.c		optional usb
 dev/usb/usb_parse.c		optional usb
 dev/usb/usb_pf.c		optional usb
 dev/usb/usb_process.c		optional usb
 dev/usb/usb_request.c		optional usb
 dev/usb/usb_transfer.c		optional usb
 dev/usb/usb_util.c		optional usb
 #
 # USB network drivers
 #
 dev/usb/net/if_aue.c		optional aue
 dev/usb/net/if_axe.c		optional axe
 dev/usb/net/if_axge.c		optional axge
 dev/usb/net/if_cdce.c		optional cdce
 dev/usb/net/if_cdceem.c		optional cdceem
 dev/usb/net/if_cue.c		optional cue
 dev/usb/net/if_ipheth.c		optional ipheth
 dev/usb/net/if_kue.c		optional kue
 dev/usb/net/if_mos.c		optional mos
 dev/usb/net/if_muge.c		optional muge
 dev/usb/net/if_rue.c		optional rue
 dev/usb/net/if_smsc.c		optional smsc
 dev/usb/net/if_udav.c		optional udav
 dev/usb/net/if_ure.c		optional ure
 dev/usb/net/if_usie.c		optional usie
 dev/usb/net/if_urndis.c		optional urndis
 dev/usb/net/ruephy.c		optional rue
 dev/usb/net/usb_ethernet.c	optional uether | aue | axe | axge | cdce | \
 					 cdceem | cue | ipheth | kue | mos | \
 					 rue | smsc | udav | ure | urndis | muge
 dev/usb/net/uhso.c		optional uhso
 #
 # USB WLAN drivers
 #
 dev/usb/wlan/if_rsu.c		optional rsu
 rsu-rtl8712fw.c			optional rsu-rtl8712fw | rsufw		\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk rsu-rtl8712fw.fw:rsu-rtl8712fw:120 -mrsu-rtl8712fw -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"rsu-rtl8712fw.c"
 rsu-rtl8712fw.fwo		optional rsu-rtl8712fw | rsufw		\
 	dependency	"rsu-rtl8712fw.fw"				\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"rsu-rtl8712fw.fwo"
 rsu-rtl8712fw.fw		optional rsu-rtl8712.fw | rsufw		\
 	dependency	"$S/contrib/dev/rsu/rsu-rtl8712fw.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"rsu-rtl8712fw.fw"
 dev/usb/wlan/if_rum.c		optional rum
 dev/usb/wlan/if_run.c		optional run
 runfw.c				optional runfw							\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk run.fw:runfw -mrunfw -c${.TARGET}"	\
 	no-ctfconvert no-implicit-rule before-depend local					\
 	clean		"runfw.c"
 runfw.fwo			optional runfw							\
 	dependency	"run.fw"								\
 	compile-with	"${NORMAL_FWO}"								\
 	no-implicit-rule									\
 	clean		"runfw.fwo"
 run.fw				optional runfw							\
 	dependency	"$S/contrib/dev/run/rt2870.fw.uu"					\
 	compile-with	"${NORMAL_FW}"								\
 	no-obj no-implicit-rule									\
 	clean		"run.fw"
 dev/usb/wlan/if_uath.c		optional uath
 dev/usb/wlan/if_upgt.c		optional upgt
 dev/usb/wlan/if_ural.c		optional ural
 dev/usb/wlan/if_urtw.c		optional urtw
 dev/usb/wlan/if_zyd.c		optional zyd
 #
 # USB serial and parallel port drivers
 #
 dev/usb/serial/u3g.c		optional u3g
 dev/usb/serial/uark.c		optional uark
 dev/usb/serial/ubsa.c		optional ubsa
 dev/usb/serial/ubser.c		optional ubser
 dev/usb/serial/uchcom.c		optional uchcom
 dev/usb/serial/ucycom.c		optional ucycom
 dev/usb/serial/ufoma.c		optional ufoma
 dev/usb/serial/uftdi.c		optional uftdi
 dev/usb/serial/ugensa.c		optional ugensa
 dev/usb/serial/uipaq.c		optional uipaq
 dev/usb/serial/ulpt.c		optional ulpt
 dev/usb/serial/umcs.c		optional umcs
 dev/usb/serial/umct.c		optional umct
 dev/usb/serial/umodem.c		optional umodem
 dev/usb/serial/umoscom.c	optional umoscom
 dev/usb/serial/uplcom.c		optional uplcom
 dev/usb/serial/uslcom.c		optional uslcom
 dev/usb/serial/uvisor.c		optional uvisor
 dev/usb/serial/uvscom.c		optional uvscom
 dev/usb/serial/usb_serial.c 	optional ucom | u3g | uark | ubsa | ubser | \
 					 uchcom | ucycom | ufoma | uftdi | \
 					 ugensa | uipaq | umcs | umct | \
 					 umodem | umoscom | uplcom | usie | \
 					 uslcom | uvisor | uvscom
 #
 # USB misc drivers
 #
 dev/usb/misc/cp2112.c		optional cp2112
 dev/usb/misc/udbp.c		optional udbp
 dev/usb/misc/ugold.c		optional ugold
 dev/usb/misc/uled.c		optional uled
 #
 # USB input drivers
 #
 dev/usb/input/atp.c		optional atp
 dev/usb/input/uep.c		optional uep
 dev/usb/input/uhid.c		optional uhid
 dev/usb/input/uhid_snes.c	optional uhid_snes
 dev/usb/input/ukbd.c		optional ukbd
 dev/usb/input/ums.c		optional ums
 dev/usb/input/usbhid.c		optional usbhid
 dev/usb/input/wmt.c		optional wmt
 dev/usb/input/wsp.c		optional wsp
 #
 # USB quirks
 #
 dev/usb/quirk/usb_quirk.c	optional usb
 #
 # USB templates
 #
 dev/usb/template/usb_template.c		optional usb_template
 dev/usb/template/usb_template_audio.c	optional usb_template
 dev/usb/template/usb_template_cdce.c	optional usb_template
 dev/usb/template/usb_template_kbd.c	optional usb_template
 dev/usb/template/usb_template_modem.c	optional usb_template
 dev/usb/template/usb_template_mouse.c	optional usb_template
 dev/usb/template/usb_template_msc.c	optional usb_template
 dev/usb/template/usb_template_mtp.c	optional usb_template
 dev/usb/template/usb_template_phone.c	optional usb_template
 dev/usb/template/usb_template_serialnet.c	optional usb_template
 dev/usb/template/usb_template_midi.c	optional usb_template
 dev/usb/template/usb_template_multi.c	optional usb_template
 dev/usb/template/usb_template_cdceem.c	optional usb_template
 #
 # USB video drivers
 #
 dev/usb/video/udl.c			optional udl
 #
 # USB END
 #
 dev/videomode/videomode.c		optional videomode
 dev/videomode/edid.c			optional videomode
 dev/videomode/pickmode.c		optional videomode
 dev/videomode/vesagtf.c			optional videomode
 dev/veriexec/verified_exec.c	optional mac_veriexec
 dev/vge/if_vge.c		optional vge
 dev/viapm/viapm.c		optional viapm pci
 dev/virtio/virtio.c			optional	virtio
 dev/virtio/virtqueue.c			optional	virtio
 dev/virtio/virtio_bus_if.m		optional	virtio
 dev/virtio/virtio_if.m			optional	virtio
 dev/virtio/pci/virtio_pci.c		optional	virtio_pci
 dev/virtio/pci/virtio_pci_if.m		optional	virtio_pci
 dev/virtio/pci/virtio_pci_legacy.c	optional	virtio_pci
 dev/virtio/pci/virtio_pci_modern.c	optional	virtio_pci
 dev/virtio/mmio/virtio_mmio.c		optional	virtio_mmio
 dev/virtio/mmio/virtio_mmio_acpi.c	optional	virtio_mmio acpi
 dev/virtio/mmio/virtio_mmio_cmdline.c	optional	virtio_mmio
 dev/virtio/mmio/virtio_mmio_fdt.c	optional	virtio_mmio fdt
 dev/virtio/mmio/virtio_mmio_if.m	optional	virtio_mmio
 dev/virtio/network/if_vtnet.c		optional	vtnet
 dev/virtio/block/virtio_blk.c		optional	virtio_blk
 dev/virtio/balloon/virtio_balloon.c	optional	virtio_balloon
 dev/virtio/gpu/virtio_gpu.c		optional	virtio_gpu
 dev/virtio/scsi/virtio_scsi.c		optional	virtio_scsi
 dev/virtio/random/virtio_random.c	optional	virtio_random
 dev/virtio/console/virtio_console.c	optional	virtio_console
 dev/vkbd/vkbd.c			optional vkbd
 dev/vmgenc/vmgenc_acpi.c	optional acpi
 dev/vmware/vmxnet3/if_vmx.c		optional vmx
 dev/vmware/vmci/vmci.c			optional vmci
 dev/vmware/vmci/vmci_datagram.c		optional vmci
 dev/vmware/vmci/vmci_doorbell.c		optional vmci
 dev/vmware/vmci/vmci_driver.c		optional vmci
 dev/vmware/vmci/vmci_event.c		optional vmci
 dev/vmware/vmci/vmci_hashtable.c	optional vmci
 dev/vmware/vmci/vmci_kernel_if.c	optional vmci
 dev/vmware/vmci/vmci_qpair.c		optional vmci
 dev/vmware/vmci/vmci_queue_pair.c	optional vmci
 dev/vmware/vmci/vmci_resource.c		optional vmci
 dev/vmware/pvscsi/pvscsi.c		optional pvscsi
 dev/vr/if_vr.c			optional vr pci
 dev/vt/colors/vt_termcolors.c	optional vt
 dev/vt/font/vt_font_default.c	optional vt
 dev/vt/font/vt_mouse_cursor.c	optional vt
 dev/vt/hw/efifb/efifb.c		optional vt_efifb
 dev/vt/hw/simplefb/simplefb.c	optional vt_simplefb fdt
 dev/vt/hw/vbefb/vbefb.c		optional vt_vbefb
 dev/vt/hw/fb/vt_fb.c		optional vt
 dev/vt/hw/vga/vt_vga.c		optional vt vt_vga
 dev/vt/logo/logo_freebsd.c	optional vt splash
 dev/vt/logo/logo_beastie.c	optional vt splash
 dev/vt/vt_buf.c			optional vt
 dev/vt/vt_consolectl.c		optional vt
 dev/vt/vt_core.c		optional vt
 dev/vt/vt_cpulogos.c		optional vt splash
 dev/vt/vt_font.c		optional vt
 dev/vt/vt_sysmouse.c		optional vt
 dev/vte/if_vte.c		optional vte pci
 dev/watchdog/watchdog.c		standard
 dev/wg/if_wg.c			optional wg				\
 	compile-with "${NORMAL_C} -include $S/dev/wg/compat.h"
 dev/wg/wg_cookie.c		optional wg				\
 	compile-with "${NORMAL_C} -include $S/dev/wg/compat.h"
 dev/wg/wg_crypto.c		optional wg				\
 	compile-with "${NORMAL_C} -include $S/dev/wg/compat.h"
 dev/wg/wg_noise.c		optional wg				\
 	compile-with "${NORMAL_C} -include $S/dev/wg/compat.h"
 dev/wpi/if_wpi.c		optional wpi pci
 wpifw.c			optional wpifw					\
 	compile-with	"${AWK} -f $S/tools/fw_stub.awk wpi.fw:wpifw:153229 -mwpi -c${.TARGET}" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean		"wpifw.c"
 wpifw.fwo			optional wpifw				\
 	dependency	"wpi.fw"					\
 	compile-with	"${NORMAL_FWO}"					\
 	no-implicit-rule						\
 	clean		"wpifw.fwo"
 wpi.fw			optional wpifw					\
 	dependency	"$S/contrib/dev/wpi/iwlwifi-3945-15.32.2.9.fw.uu"	\
 	compile-with	"${NORMAL_FW}"					\
 	no-obj no-implicit-rule						\
 	clean		"wpi.fw"
 dev/xdma/controller/pl330.c	optional xdma pl330 fdt
 dev/xdma/xdma.c			optional xdma
 dev/xdma/xdma_bank.c		optional xdma
 dev/xdma/xdma_bio.c		optional xdma
 dev/xdma/xdma_fdt_test.c	optional xdma xdma_test fdt
 dev/xdma/xdma_if.m		optional xdma
 dev/xdma/xdma_iommu.c		optional xdma
 dev/xdma/xdma_mbuf.c		optional xdma
 dev/xdma/xdma_queue.c		optional xdma
 dev/xdma/xdma_sg.c		optional xdma
 dev/xdma/xdma_sglist.c		optional xdma
 dev/xen/balloon/balloon.c	optional xenhvm
 dev/xen/blkfront/blkfront.c	optional xenhvm
 dev/xen/blkback/blkback.c	optional xenhvm
 dev/xen/bus/xen_intr.c		optional xenhvm
 dev/xen/bus/xenpv.c		optional xenhvm
 dev/xen/console/xen_console.c	optional xenhvm
 dev/xen/control/control.c	optional xenhvm
 dev/xen/cpu/xen_acpi_cpu.c	optional xenhvm
 dev/xen/efi/pvefi.c		optional xenhvm xenefi efirt
 dev/xen/grant_table/grant_table.c	optional xenhvm
 dev/xen/netback/netback.c	optional xenhvm
 dev/xen/netfront/netfront.c	optional xenhvm
 dev/xen/timer/xen_timer.c	optional xenhvm xentimer
 dev/xen/xenpci/xenpci.c		optional xenpci
 dev/xen/xenstore/xenstore.c	optional xenhvm
 dev/xen/xenstore/xenstore_dev.c	optional xenhvm
 dev/xen/xenstore/xenstored_dev.c	optional xenhvm
 dev/xen/evtchn/evtchn_dev.c	optional xenhvm
 dev/xen/privcmd/privcmd.c	optional xenhvm
 dev/xen/gntdev/gntdev.c		optional xenhvm
 dev/xen/debug/debug.c		optional xenhvm
 dev/xl/if_xl.c			optional xl pci
 dev/xl/xlphy.c			optional xl pci
 fs/autofs/autofs.c		optional autofs
 fs/autofs/autofs_vfsops.c	optional autofs
 fs/autofs/autofs_vnops.c	optional autofs
 fs/deadfs/dead_vnops.c		standard
 fs/devfs/devfs_devs.c		standard
 fs/devfs/devfs_dir.c		standard
 fs/devfs/devfs_rule.c		standard
 fs/devfs/devfs_vfsops.c		standard
 fs/devfs/devfs_vnops.c		standard
 fs/fdescfs/fdesc_vfsops.c	optional fdescfs
 fs/fdescfs/fdesc_vnops.c	optional fdescfs
 fs/fifofs/fifo_vnops.c		standard
 fs/cuse/cuse.c			optional cuse
 fs/fuse/fuse_device.c		optional fusefs
 fs/fuse/fuse_file.c		optional fusefs
 fs/fuse/fuse_internal.c		optional fusefs
 fs/fuse/fuse_io.c		optional fusefs
 fs/fuse/fuse_ipc.c		optional fusefs
 fs/fuse/fuse_main.c		optional fusefs
 fs/fuse/fuse_node.c		optional fusefs
 fs/fuse/fuse_vfsops.c		optional fusefs
 fs/fuse/fuse_vnops.c		optional fusefs
 fs/mntfs/mntfs_vnops.c		standard
 fs/msdosfs/msdosfs_conv.c	optional msdosfs
 fs/msdosfs/msdosfs_denode.c	optional msdosfs
 fs/msdosfs/msdosfs_fat.c	optional msdosfs
 fs/msdosfs/msdosfs_iconv.c	optional msdosfs_iconv
 fs/msdosfs/msdosfs_lookup.c	optional msdosfs
 fs/msdosfs/msdosfs_vfsops.c	optional msdosfs
 fs/msdosfs/msdosfs_vnops.c	optional msdosfs
 fs/nfs/nfs_commonkrpc.c		optional nfscl | nfslockd | nfsd
 fs/nfs/nfs_commonsubs.c		optional nfscl | nfslockd | nfsd
 fs/nfs/nfs_commonport.c		optional nfscl | nfslockd | nfsd
 fs/nfs/nfs_commonacl.c		optional nfscl | nfslockd | nfsd
 fs/nfsclient/nfs_clcomsubs.c	optional nfscl
 fs/nfsclient/nfs_clsubs.c	optional nfscl
 fs/nfsclient/nfs_clstate.c	optional nfscl
 fs/nfsclient/nfs_clkrpc.c	optional nfscl
 fs/nfsclient/nfs_clrpcops.c	optional nfscl
 fs/nfsclient/nfs_clvnops.c	optional nfscl
 fs/nfsclient/nfs_clnode.c	optional nfscl
 fs/nfsclient/nfs_clvfsops.c	optional nfscl
 fs/nfsclient/nfs_clport.c	optional nfscl
 fs/nfsclient/nfs_clbio.c	optional nfscl
 fs/nfsclient/nfs_clnfsiod.c	optional nfscl
 fs/nfsserver/nfs_fha_new.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdsocket.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdsubs.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdstate.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdkrpc.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdserv.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdport.c	optional nfsd inet
 fs/nfsserver/nfs_nfsdcache.c	optional nfsd inet
 fs/nullfs/null_subr.c		optional nullfs
 fs/nullfs/null_vfsops.c		optional nullfs
 fs/nullfs/null_vnops.c		optional nullfs
 fs/procfs/procfs.c		optional procfs
 fs/procfs/procfs_dbregs.c	optional procfs
 fs/procfs/procfs_fpregs.c	optional procfs
 fs/procfs/procfs_map.c		optional procfs
 fs/procfs/procfs_mem.c		optional procfs
 fs/procfs/procfs_note.c		optional procfs
 fs/procfs/procfs_osrel.c	optional procfs
 fs/procfs/procfs_regs.c		optional procfs
 fs/procfs/procfs_rlimit.c	optional procfs
 fs/procfs/procfs_status.c	optional procfs
 fs/procfs/procfs_type.c		optional procfs
 fs/pseudofs/pseudofs.c		optional pseudofs
 fs/pseudofs/pseudofs_fileno.c	optional pseudofs
 fs/pseudofs/pseudofs_vncache.c	optional pseudofs
 fs/pseudofs/pseudofs_vnops.c	optional pseudofs
 fs/smbfs/smbfs_io.c		optional smbfs
 fs/smbfs/smbfs_node.c		optional smbfs
 fs/smbfs/smbfs_smb.c		optional smbfs
 fs/smbfs/smbfs_subr.c		optional smbfs
 fs/smbfs/smbfs_vfsops.c		optional smbfs
 fs/smbfs/smbfs_vnops.c		optional smbfs
 fs/tarfs/tarfs_io.c		optional tarfs compile-with "${NORMAL_C} -I$S/contrib/zstd/lib/freebsd"
 fs/tarfs/tarfs_subr.c		optional tarfs
 fs/tarfs/tarfs_vfsops.c		optional tarfs
 fs/tarfs/tarfs_vnops.c		optional tarfs
 fs/udf/osta.c			optional udf
 fs/udf/udf_iconv.c		optional udf_iconv
 fs/udf/udf_vfsops.c		optional udf
 fs/udf/udf_vnops.c		optional udf
 fs/unionfs/union_subr.c		optional unionfs
 fs/unionfs/union_vfsops.c	optional unionfs
 fs/unionfs/union_vnops.c	optional unionfs
 fs/tmpfs/tmpfs_vnops.c		optional tmpfs
 fs/tmpfs/tmpfs_fifoops.c 	optional tmpfs
 fs/tmpfs/tmpfs_vfsops.c 	optional tmpfs
 fs/tmpfs/tmpfs_subr.c 		optional tmpfs
 gdb/gdb_cons.c			optional gdb
 gdb/gdb_main.c			optional gdb
 gdb/gdb_packet.c		optional gdb
 gdb/netgdb.c			optional ddb debugnet gdb netgdb inet
 geom/bde/g_bde.c		optional geom_bde
 geom/bde/g_bde_crypt.c		optional geom_bde
 geom/bde/g_bde_lock.c		optional geom_bde
 geom/bde/g_bde_work.c		optional geom_bde
 geom/cache/g_cache.c		optional geom_cache
 geom/concat/g_concat.c		optional geom_concat
 geom/eli/g_eli.c		optional geom_eli
 geom/eli/g_eli_crypto.c		optional geom_eli
 geom/eli/g_eli_ctl.c		optional geom_eli
 geom/eli/g_eli_hmac.c		optional geom_eli
 geom/eli/g_eli_integrity.c	optional geom_eli
 geom/eli/g_eli_key.c		optional geom_eli
 geom/eli/g_eli_key_cache.c	optional geom_eli
 geom/eli/g_eli_privacy.c	optional geom_eli
 geom/eli/pkcs5v2.c		optional geom_eli
 geom/gate/g_gate.c		optional geom_gate
 geom/geom_bsd_enc.c		optional geom_part_bsd
 geom/geom_ccd.c			optional ccd | geom_ccd
 geom/geom_ctl.c			standard
 geom/geom_dev.c			standard
 geom/geom_disk.c		standard
 geom/geom_dump.c		standard
 geom/geom_event.c		standard
 geom/geom_flashmap.c		optional fdt cfi | fdt mx25l | mmcsd | fdt n25q | fdt at45d
 geom/geom_io.c			standard
 geom/geom_kern.c		standard
 geom/geom_map.c			optional geom_map
 geom/geom_redboot.c		optional geom_redboot
 geom/geom_slice.c		standard
 geom/geom_subr.c		standard
 geom/geom_vfs.c			standard
 geom/journal/g_journal.c	optional geom_journal
 geom/journal/g_journal_ufs.c	optional geom_journal
 geom/label/g_label.c		optional geom_label | geom_label_gpt
 geom/label/g_label_ext2fs.c	optional geom_label
 geom/label/g_label_flashmap.c	optional geom_label
 geom/label/g_label_iso9660.c	optional geom_label
 geom/label/g_label_msdosfs.c	optional geom_label
 geom/label/g_label_ntfs.c	optional geom_label
 geom/label/g_label_reiserfs.c	optional geom_label
 geom/label/g_label_ufs.c	optional geom_label
 geom/label/g_label_gpt.c	optional geom_label | geom_label_gpt
 geom/label/g_label_disk_ident.c	optional geom_label
 geom/linux_lvm/g_linux_lvm.c	optional geom_linux_lvm
 geom/mirror/g_mirror.c		optional geom_mirror
 geom/mirror/g_mirror_ctl.c	optional geom_mirror
 geom/mountver/g_mountver.c	optional geom_mountver
 geom/multipath/g_multipath.c	optional geom_multipath
 geom/nop/g_nop.c		optional geom_nop
 geom/part/g_part.c		standard
 geom/part/g_part_if.m		standard
 geom/part/g_part_apm.c		optional geom_part_apm
 geom/part/g_part_bsd.c		optional geom_part_bsd
 geom/part/g_part_bsd64.c	optional geom_part_bsd64
 geom/part/g_part_ebr.c		optional geom_part_ebr
 geom/part/g_part_gpt.c		optional geom_part_gpt
 geom/part/g_part_ldm.c		optional geom_part_ldm
 geom/part/g_part_mbr.c		optional geom_part_mbr
 geom/raid/g_raid.c		optional geom_raid
 geom/raid/g_raid_ctl.c		optional geom_raid
 geom/raid/g_raid_md_if.m	optional geom_raid
 geom/raid/g_raid_tr_if.m	optional geom_raid
 geom/raid/md_ddf.c		optional geom_raid
 geom/raid/md_intel.c		optional geom_raid
 geom/raid/md_jmicron.c		optional geom_raid
 geom/raid/md_nvidia.c		optional geom_raid
 geom/raid/md_promise.c		optional geom_raid
 geom/raid/md_sii.c		optional geom_raid
 geom/raid/tr_concat.c		optional geom_raid
 geom/raid/tr_raid0.c		optional geom_raid
 geom/raid/tr_raid1.c		optional geom_raid
 geom/raid/tr_raid1e.c		optional geom_raid
 geom/raid/tr_raid5.c		optional geom_raid
 geom/raid3/g_raid3.c		optional geom_raid3
 geom/raid3/g_raid3_ctl.c	optional geom_raid3
 geom/shsec/g_shsec.c		optional geom_shsec
 geom/stripe/g_stripe.c		optional geom_stripe
 geom/union/g_union.c		optional geom_union
 geom/uzip/g_uzip.c		optional geom_uzip
 geom/uzip/g_uzip_lzma.c		optional geom_uzip
 geom/uzip/g_uzip_wrkthr.c	optional geom_uzip
 geom/uzip/g_uzip_zlib.c		optional geom_uzip
 geom/uzip/g_uzip_zstd.c		optional geom_uzip zstdio \
 	compile-with "${NORMAL_C} -I$S/contrib/zstd/lib/freebsd"
 geom/vinum/geom_vinum.c		optional geom_vinum
 geom/vinum/geom_vinum_create.c	optional geom_vinum
 geom/vinum/geom_vinum_drive.c	optional geom_vinum
 geom/vinum/geom_vinum_plex.c	optional geom_vinum
 geom/vinum/geom_vinum_volume.c	optional geom_vinum
 geom/vinum/geom_vinum_subr.c	optional geom_vinum
 geom/vinum/geom_vinum_raid5.c	optional geom_vinum
 geom/vinum/geom_vinum_share.c	optional geom_vinum
 geom/vinum/geom_vinum_list.c	optional geom_vinum
 geom/vinum/geom_vinum_rm.c	optional geom_vinum
 geom/vinum/geom_vinum_init.c	optional geom_vinum
 geom/vinum/geom_vinum_state.c	optional geom_vinum
 geom/vinum/geom_vinum_rename.c	optional geom_vinum
 geom/vinum/geom_vinum_move.c	optional geom_vinum
 geom/vinum/geom_vinum_events.c	optional geom_vinum
 geom/virstor/binstream.c	optional geom_virstor
 geom/virstor/g_virstor.c	optional geom_virstor
 geom/virstor/g_virstor_md.c	optional geom_virstor
 geom/zero/g_zero.c		optional geom_zero
 fs/ext2fs/ext2_acl.c		optional ext2fs
 fs/ext2fs/ext2_alloc.c		optional ext2fs
 fs/ext2fs/ext2_balloc.c		optional ext2fs
 fs/ext2fs/ext2_bmap.c		optional ext2fs
 fs/ext2fs/ext2_csum.c		optional ext2fs
 fs/ext2fs/ext2_extattr.c	optional ext2fs
 fs/ext2fs/ext2_extents.c	optional ext2fs
 fs/ext2fs/ext2_inode.c		optional ext2fs
 fs/ext2fs/ext2_inode_cnv.c	optional ext2fs
 fs/ext2fs/ext2_hash.c		optional ext2fs
 fs/ext2fs/ext2_htree.c		optional ext2fs
 fs/ext2fs/ext2_lookup.c		optional ext2fs
 fs/ext2fs/ext2_subr.c		optional ext2fs
 fs/ext2fs/ext2_vfsops.c		optional ext2fs
 fs/ext2fs/ext2_vnops.c		optional ext2fs
 #
 isa/isa_if.m			standard
 isa/isa_common.c		optional isa
 isa/isahint.c			optional isa
 isa/pnp.c			optional isa isapnp
 isa/pnpparse.c			optional isa isapnp
 fs/cd9660/cd9660_bmap.c	optional cd9660
 fs/cd9660/cd9660_lookup.c	optional cd9660
 fs/cd9660/cd9660_node.c	optional cd9660
 fs/cd9660/cd9660_rrip.c	optional cd9660
 fs/cd9660/cd9660_util.c	optional cd9660
 fs/cd9660/cd9660_vfsops.c	optional cd9660
 fs/cd9660/cd9660_vnops.c	optional cd9660
 fs/cd9660/cd9660_iconv.c	optional cd9660_iconv
 gnu/gcov/gcc_4_7.c		optional gcov  \
 	warning "kernel contains GPL licensed gcov support"
 gnu/gcov/gcov_fs.c		optional gcov  lindebugfs \
 	compile-with "${LINUXKPI_C}"
 gnu/gcov/gcov_subr.c		optional gcov
 
 kern/bus_if.m			standard
 kern/clock_if.m			standard
 kern/cpufreq_if.m		standard
 kern/device_if.m		standard
 kern/imgact_binmisc.c		optional imgact_binmisc
 kern/imgact_elf.c		standard
 kern/imgact_elf32.c		optional compat_freebsd32
 kern/imgact_shell.c		standard
 kern/init_main.c		standard
 kern/init_sysent.c		standard
 kern/ksched.c			optional _kposix_priority_scheduling
 kern/kern_acct.c		standard
 kern/kern_alq.c			optional alq
 kern/kern_boottrace.c		standard
 kern/kern_clock.c		standard
 kern/kern_clocksource.c		standard
 kern/kern_condvar.c		standard
 kern/kern_conf.c		standard
 kern/kern_cons.c		standard
 kern/kern_cpu.c			standard
 kern/kern_cpuset.c		standard
 kern/kern_context.c		standard
 kern/kern_descrip.c		standard
 kern/kern_devctl.c		standard
 kern/kern_dtrace.c		optional kdtrace_hooks
 kern/kern_dump.c		standard
 kern/kern_environment.c		standard
 kern/kern_et.c			standard
 kern/kern_event.c		standard
 kern/kern_exec.c		standard
 kern/kern_exit.c		standard
 kern/kern_fail.c		standard
 kern/kern_ffclock.c		standard
 kern/kern_fork.c		standard
 kern/kern_hhook.c		standard
 kern/kern_idle.c		standard
 kern/kern_intr.c		standard
 kern/kern_jail.c		standard
 kern/kern_kcov.c		optional kcov			\
 	compile-with "${NORMAL_C:N-fsanitize*} ${NORMAL_C:M-fsanitize=kernel-memory}"
 kern/kern_khelp.c		standard
 kern/kern_kthread.c		standard
 kern/kern_ktr.c			optional ktr
 kern/kern_ktrace.c		standard
 kern/kern_linker.c		standard
 kern/kern_lock.c		standard
 kern/kern_lockf.c		standard
 kern/kern_lockstat.c		optional kdtrace_hooks
 kern/kern_loginclass.c		standard
 kern/kern_malloc.c		standard
 kern/kern_mbuf.c		standard
 kern/kern_membarrier.c		standard
 kern/kern_mib.c			standard
 kern/kern_module.c		standard
 kern/kern_mtxpool.c		standard
 kern/kern_mutex.c		standard
 kern/kern_ntptime.c		standard
 kern/kern_osd.c			standard
 kern/kern_physio.c		standard
 kern/kern_pmc.c			standard
 kern/kern_poll.c		optional device_polling
 kern/kern_priv.c		standard
 kern/kern_proc.c		standard
 kern/kern_procctl.c		standard
 kern/kern_prot.c		standard
 kern/kern_racct.c		standard
 kern/kern_rangelock.c		standard
 kern/kern_rctl.c		standard
 kern/kern_resource.c		standard
 kern/kern_rmlock.c		standard
 kern/kern_rwlock.c		standard
 kern/kern_sdt.c			optional kdtrace_hooks
 kern/kern_sema.c		standard
 kern/kern_sendfile.c		standard
 kern/kern_sharedpage.c		standard
 kern/kern_shutdown.c		standard
 kern/kern_sig.c			standard
 kern/kern_switch.c		standard
 kern/kern_sx.c			standard
 kern/kern_synch.c		standard
 kern/kern_syscalls.c		standard
 kern/kern_sysctl.c		standard
 kern/kern_tc.c			standard
 kern/kern_thr.c			standard
 kern/kern_thread.c		standard
 kern/kern_time.c		standard
 kern/kern_timeout.c		standard
 kern/kern_tslog.c		optional tslog
 kern/kern_ubsan.c		optional kubsan
 kern/kern_umtx.c		standard
 kern/kern_uuid.c		standard
 kern/kern_vnodedumper.c		standard
 kern/kern_xxx.c			standard
 kern/link_elf.c			standard
 kern/linker_if.m		standard
 kern/md4c.c			optional netsmb
 kern/md5c.c			standard
 kern/p1003_1b.c			standard
 kern/posix4_mib.c		standard
 kern/sched_4bsd.c		optional sched_4bsd
 kern/sched_ule.c		optional sched_ule
 kern/serdev_if.m		standard
 kern/stack_protector.c		standard \
 	compile-with "${NORMAL_C:N-fstack-protector*}"
 kern/subr_acl_nfs4.c		optional ufs_acl | zfs
 kern/subr_acl_posix1e.c		optional ufs_acl
 kern/subr_asan.c		optional kasan \
 	compile-with "${NORMAL_C:N-fsanitize*:N-fstack-protector*}"
 kern/subr_autoconf.c		standard
 kern/subr_blist.c		standard
 kern/subr_boot.c		standard
 kern/subr_bus.c			standard
 kern/subr_bus_dma.c		standard
 kern/subr_bufring.c		standard
 kern/subr_capability.c		standard
 kern/subr_clock.c		standard
 kern/subr_compressor.c		standard \
 	compile-with "${NORMAL_C} -I$S/contrib/zstd/lib/freebsd"
 kern/subr_coverage.c		optional coverage \
 	compile-with "${NORMAL_C:N-fsanitize*}"
 kern/subr_counter.c		standard
 kern/subr_csan.c		optional kcsan \
 	compile-with "${NORMAL_C:N-fsanitize*:N-fstack-protector*}"
 kern/subr_devstat.c		standard
 kern/subr_disk.c		standard
 kern/subr_early.c		standard
 kern/subr_epoch.c		standard
 kern/subr_eventhandler.c	standard
 kern/subr_fattime.c		standard
 kern/subr_firmware.c		optional firmware
 kern/subr_filter.c		standard
 kern/subr_gtaskqueue.c		standard
 kern/subr_hash.c		standard
 kern/subr_hints.c		standard
 kern/subr_kdb.c			standard
 kern/subr_kobj.c		standard
 kern/subr_lock.c		standard
 kern/subr_log.c			standard
 kern/subr_mchain.c		optional libmchain
 kern/subr_memdesc.c		standard
 kern/subr_module.c		standard
 kern/subr_msan.c		optional kmsan \
 	compile-with "${NORMAL_C:N-fsanitize*:N-fno-sanitize*:N-fstack-protector*}"
 kern/subr_msgbuf.c		standard
 kern/subr_param.c		standard
 kern/subr_pcpu.c		standard
 kern/subr_pctrie.c		standard
 kern/subr_pidctrl.c		standard
 kern/subr_power.c		standard
 kern/subr_prf.c			standard
 kern/subr_prng.c		standard
 kern/subr_prof.c		standard
 kern/subr_rangeset.c		standard
 kern/subr_rman.c		standard
 kern/subr_rtc.c			standard
 kern/subr_sbuf.c		standard
 kern/subr_scanf.c		standard
 kern/subr_sglist.c		standard
 kern/subr_sleepqueue.c		standard
 kern/subr_smp.c			standard
 kern/subr_smr.c			standard
 kern/subr_stack.c		optional ddb | stack | ktr
 kern/subr_stats.c		optional stats
 kern/subr_taskqueue.c		standard
 kern/subr_terminal.c		optional vt
 kern/subr_trap.c		standard
 kern/subr_turnstile.c		standard
 kern/subr_uio.c			standard
 kern/subr_unit.c		standard
 kern/subr_vmem.c		standard
 kern/subr_witness.c		optional witness
 kern/sys_capability.c		standard
 kern/sys_eventfd.c		standard
 kern/sys_generic.c		standard
 kern/sys_getrandom.c		standard
 kern/sys_pipe.c			standard
 kern/sys_procdesc.c		standard
 kern/sys_process.c		standard
 kern/sys_socket.c		standard
 kern/sys_timerfd.c		standard
 kern/syscalls.c			standard
 kern/sysv_ipc.c			standard
 kern/sysv_msg.c			optional sysvmsg
 kern/sysv_sem.c			optional sysvsem
 kern/sysv_shm.c			optional sysvshm
 kern/tty.c			standard
 kern/tty_compat.c		optional compat_43tty
 kern/tty_info.c			standard
 kern/tty_inq.c			standard
 kern/tty_outq.c			standard
 kern/tty_pts.c			standard
 kern/tty_tty.c			standard
 kern/tty_ttydisc.c		standard
 kern/uipc_accf.c		standard
 kern/uipc_debug.c		optional ddb
 kern/uipc_domain.c		standard
 kern/uipc_ktls.c		optional kern_tls
 kern/uipc_mbuf.c		standard
 kern/uipc_mbuf2.c		standard
 kern/uipc_mbufhash.c		standard
 kern/uipc_mqueue.c		optional p1003_1b_mqueue
 kern/uipc_sem.c			optional p1003_1b_semaphores
 kern/uipc_shm.c			standard
 kern/uipc_sockbuf.c		standard
 kern/uipc_socket.c		standard
 kern/uipc_syscalls.c		standard
 kern/uipc_usrreq.c		standard
 kern/vfs_acl.c			standard
 kern/vfs_aio.c			standard
 kern/vfs_bio.c			standard
 kern/vfs_cache.c		standard
 kern/vfs_cluster.c		standard
 kern/vfs_default.c		standard
 kern/vfs_export.c		standard
 kern/vfs_extattr.c		standard
 kern/vfs_hash.c			standard
 kern/vfs_init.c			standard
 kern/vfs_lookup.c		standard
 kern/vfs_mount.c		standard
 kern/vfs_mountroot.c		standard
 kern/vfs_subr.c			standard
 kern/vfs_syscalls.c		standard
 kern/vfs_vnops.c		standard
 #
 # Kernel GSS-API
 #
 gssd.h				optional kgssapi			\
 	dependency		"$S/kgssapi/gssd.x"			\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h" \
 	no-obj no-implicit-rule before-depend local			\
 	clean			"gssd.h"
 gssd_xdr.c			optional kgssapi			\
 	dependency		"$S/kgssapi/gssd.x gssd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean			"gssd_xdr.c"
 gssd_clnt.c			optional kgssapi			\
 	dependency		"$S/kgssapi/gssd.x gssd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c" \
 	no-ctfconvert no-implicit-rule before-depend local		\
 	clean			"gssd_clnt.c"
 kgssapi/gss_accept_sec_context.c optional kgssapi
 kgssapi/gss_add_oid_set_member.c optional kgssapi
 kgssapi/gss_acquire_cred.c	optional kgssapi
 kgssapi/gss_canonicalize_name.c	optional kgssapi
 kgssapi/gss_create_empty_oid_set.c optional kgssapi
 kgssapi/gss_delete_sec_context.c optional kgssapi
 kgssapi/gss_display_status.c	optional kgssapi
 kgssapi/gss_export_name.c	optional kgssapi
 kgssapi/gss_get_mic.c		optional kgssapi
 kgssapi/gss_init_sec_context.c	optional kgssapi
 kgssapi/gss_impl.c		optional kgssapi
 kgssapi/gss_import_name.c	optional kgssapi
+kgssapi/gss_ip_to_dns.c		optional kgssapi
 kgssapi/gss_names.c		optional kgssapi
 kgssapi/gss_pname_to_uid.c	optional kgssapi
 kgssapi/gss_release_buffer.c	optional kgssapi
 kgssapi/gss_release_cred.c	optional kgssapi
 kgssapi/gss_release_name.c	optional kgssapi
 kgssapi/gss_release_oid_set.c	optional kgssapi
 kgssapi/gss_set_cred_option.c	optional kgssapi
 kgssapi/gss_test_oid_set_member.c optional kgssapi
 kgssapi/gss_unwrap.c		optional kgssapi
 kgssapi/gss_verify_mic.c	optional kgssapi
 kgssapi/gss_wrap.c		optional kgssapi
 kgssapi/gss_wrap_size_limit.c	optional kgssapi
 kgssapi/gssd_prot.c		optional kgssapi
 kgssapi/krb5/krb5_mech.c	optional kgssapi
 kgssapi/krb5/kcrypto.c		optional kgssapi
 kgssapi/krb5/kcrypto_aes.c	optional kgssapi
 kgssapi/kgss_if.m		optional kgssapi
 kgssapi/gsstest.c		optional kgssapi_debug
 # These files in libkern/ are those needed by all architectures.  Some
 # of the files in libkern/ are only needed on some architectures, e.g.,
 # libkern/divdi3.c is needed by i386 but not alpha.  Also, some of these
 # routines may be optimized for a particular platform.  In either case,
 # the file should be moved to conf/files.<arch> from here.
 #
 libkern/arc4random.c		standard
 libkern/arc4random_uniform.c	standard
 libkern/asprintf.c		standard
 libkern/bcd.c			standard
 libkern/bsearch.c		standard
 libkern/crc16.c			standard
 libkern/explicit_bzero.c	standard
 libkern/fnmatch.c		standard
 libkern/gsb_crc32.c		standard
 libkern/iconv.c			optional libiconv
 libkern/iconv_converter_if.m	optional libiconv
 libkern/iconv_ucs.c		optional libiconv
 libkern/iconv_xlat.c		optional libiconv
 libkern/iconv_xlat16.c		optional libiconv
 libkern/inet_aton.c		standard
 libkern/inet_ntoa.c		standard
 libkern/inet_ntop.c		standard
 libkern/inet_pton.c		standard
 libkern/jenkins_hash.c		standard
 libkern/murmur3_32.c		standard
 libkern/memcchr.c		standard
 libkern/memchr.c		standard
 libkern/memmem.c		optional gdb
 libkern/qsort.c			standard
 libkern/qsort_r.c		standard
 libkern/random.c		standard
 libkern/scanc.c			standard
 libkern/strcasecmp.c		standard
 libkern/strcasestr.c		standard
 libkern/strcat.c		standard
 libkern/strchr.c		standard
 libkern/strchrnul.c		standard
 libkern/strcpy.c		standard
 libkern/strcspn.c		standard
 libkern/strdup.c		standard
 libkern/strndup.c		standard
 libkern/strlcat.c		standard
 libkern/strlcpy.c		standard
 libkern/strncat.c		standard
 libkern/strncpy.c		standard
 libkern/strnlen.c		standard
 libkern/strnstr.c		standard
 libkern/strrchr.c		standard
 libkern/strsep.c		standard
 libkern/strspn.c		standard
 libkern/strstr.c		standard
 libkern/strtol.c		standard
 libkern/strtoq.c		standard
 libkern/strtoul.c		standard
 libkern/strtouq.c		standard
 libkern/strvalid.c		standard
 libkern/timingsafe_bcmp.c	standard
 contrib/zlib/adler32.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/compress.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/crc32.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/deflate.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/inffast.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/inflate.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/inftrees.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/trees.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/uncompr.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 contrib/zlib/zutil.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib \
 	compile-with "${ZLIB_C}"
 dev/zlib/zlib_mod.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib
 dev/zlib/zcalloc.c		optional crypto | geom_uzip | \
 	mxge | ddb_ctf | gzio | zfs | zlib
 net/altq/altq_cbq.c		optional altq
 net/altq/altq_codel.c		optional altq
 net/altq/altq_hfsc.c		optional altq
 net/altq/altq_fairq.c		optional altq
 net/altq/altq_priq.c		optional altq
 net/altq/altq_red.c		optional altq
 net/altq/altq_rio.c		optional altq
 net/altq/altq_rmclass.c		optional altq
 net/altq/altq_subr.c		optional altq
 net/bpf.c			standard
 net/bpf_buffer.c		optional bpf
 net/bpf_jitter.c		optional bpf_jitter
 net/bpf_filter.c		optional bpf | netgraph_bpf
 net/bpf_zerocopy.c		optional bpf
 net/bridgestp.c			optional bridge | if_bridge
 net/ieee8023ad_lacp.c		optional lagg
 net/if.c			standard
 net/ifq.c			standard
 net/if_bridge.c			optional bridge inet | if_bridge inet
 net/if_clone.c			standard
 net/if_dead.c			standard
 net/if_disc.c			optional disc
 net/if_edsc.c			optional edsc
 net/if_enc.c			optional enc inet | enc inet6
 net/if_epair.c			optional epair
 net/if_ethersubr.c		optional ether
 net/if_fwsubr.c			optional fwip
 net/if_gif.c			optional gif inet | gif inet6 | \
 					 netgraph_gif inet | netgraph_gif inet6
 net/if_gre.c			optional gre inet | gre inet6
 net/if_ipsec.c			optional inet ipsec | inet6 ipsec
 net/if_lagg.c			optional lagg
 net/if_loop.c			optional loop
 net/if_llatbl.c			standard
 net/if_me.c			optional me inet
 net/if_media.c			standard
 net/if_mib.c			standard
 net/if_ovpn.c			optional ovpn inet | ovpn inet6
 net/if_stf.c			optional stf inet inet6
 net/if_tuntap.c			optional tuntap
 net/if_vlan.c			optional vlan
 net/if_vxlan.c			optional vxlan inet | vxlan inet6
 net/ifdi_if.m			optional ether pci iflib
 net/iflib.c			optional ether pci iflib
 net/mp_ring.c			optional ether iflib
 net/mppcc.c			optional netgraph_mppc_compression
 net/mppcd.c			optional netgraph_mppc_compression
 net/netisr.c			standard
 net/debugnet.c			optional inet debugnet
 net/debugnet_inet.c		optional inet debugnet
 net/pfil.c			optional ether | inet
 net/radix.c			standard
 net/route.c			standard
 net/route/nhgrp.c		optional route_mpath
 net/route/nhgrp_ctl.c		optional route_mpath
 net/route/nhop.c		standard
 net/route/nhop_ctl.c		standard
 net/route/nhop_utils.c		standard
 net/route/fib_algo.c		optional fib_algo
 net/route/route_ctl.c		standard
 net/route/route_ddb.c		optional ddb
 net/route/route_helpers.c	standard
 net/route/route_ifaddrs.c	standard
 net/route/route_rtentry.c	standard
 net/route/route_subscription.c	standard
 net/route/route_tables.c	standard
 net/route/route_temporal.c	standard
 net/rss_config.c		optional inet rss | inet6 rss
 net/rtsock.c			standard
 net/slcompress.c		optional netgraph_vjc
 net/toeplitz.c			optional inet rss | inet6 rss | route_mpath
 net/vnet.c			optional vimage
 net80211/ieee80211.c		optional wlan
 net80211/ieee80211_acl.c	optional wlan wlan_acl
 net80211/ieee80211_action.c	optional wlan
 net80211/ieee80211_adhoc.c	optional wlan \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_ageq.c	optional wlan
 net80211/ieee80211_amrr.c	optional wlan | wlan_amrr
 net80211/ieee80211_crypto.c	optional wlan \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_crypto_ccmp.c optional wlan wlan_ccmp
 net80211/ieee80211_crypto_none.c optional wlan
 net80211/ieee80211_crypto_tkip.c optional wlan wlan_tkip
 net80211/ieee80211_crypto_wep.c	optional wlan wlan_wep
 net80211/ieee80211_ddb.c	optional wlan ddb
 net80211/ieee80211_dfs.c	optional wlan
 net80211/ieee80211_freebsd.c	optional wlan
 net80211/ieee80211_hostap.c	optional wlan \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_ht.c		optional wlan
 net80211/ieee80211_hwmp.c	optional wlan ieee80211_support_mesh
 net80211/ieee80211_input.c	optional wlan
 net80211/ieee80211_ioctl.c	optional wlan
 net80211/ieee80211_mesh.c	optional wlan ieee80211_support_mesh \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_monitor.c	optional wlan
 net80211/ieee80211_node.c	optional wlan
 net80211/ieee80211_output.c	optional wlan
 net80211/ieee80211_phy.c	optional wlan
 net80211/ieee80211_power.c	optional wlan
 net80211/ieee80211_proto.c	optional wlan
 net80211/ieee80211_radiotap.c	optional wlan
 net80211/ieee80211_ratectl.c	optional wlan
 net80211/ieee80211_ratectl_none.c optional wlan
 net80211/ieee80211_regdomain.c	optional wlan
 net80211/ieee80211_rssadapt.c	optional wlan wlan_rssadapt
 net80211/ieee80211_scan.c	optional wlan
 net80211/ieee80211_scan_sta.c	optional wlan
 net80211/ieee80211_sta.c	optional wlan \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_superg.c	optional wlan ieee80211_support_superg
 net80211/ieee80211_scan_sw.c	optional wlan
 net80211/ieee80211_tdma.c	optional wlan ieee80211_support_tdma
 net80211/ieee80211_vht.c	optional wlan
 net80211/ieee80211_wds.c	optional wlan
 net80211/ieee80211_xauth.c	optional wlan wlan_xauth
 net80211/ieee80211_alq.c	optional wlan ieee80211_alq
 netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth
 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt usb
 netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c optional netgraph_bluetooth_ubt usb
 netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw usb
 netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci
 netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci
 netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci
 netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci
 netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci
 netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap
 netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket
 netgraph/bluetooth/socket/ng_btsocket_hci_raw.c	optional netgraph_bluetooth_socket
 netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket
 netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket
 netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket
 netgraph/bluetooth/socket/ng_btsocket_sco.c optional netgraph_bluetooth_socket
 netgraph/netflow/netflow.c	optional netgraph_netflow
 netgraph/netflow/netflow_v9.c	optional netgraph_netflow
 netgraph/netflow/ng_netflow.c	optional netgraph_netflow
 netgraph/ng_UI.c		optional netgraph_UI
 netgraph/ng_async.c		optional netgraph_async
 netgraph/ng_base.c		optional netgraph
 netgraph/ng_bpf.c		optional netgraph_bpf
 netgraph/ng_bridge.c		optional netgraph_bridge
 netgraph/ng_car.c		optional netgraph_car
 netgraph/ng_checksum.c		optional netgraph_checksum
 netgraph/ng_cisco.c		optional netgraph_cisco
 netgraph/ng_deflate.c		optional netgraph_deflate
 netgraph/ng_device.c		optional netgraph_device
 netgraph/ng_echo.c		optional netgraph_echo
 netgraph/ng_eiface.c		optional netgraph_eiface
 netgraph/ng_ether.c		optional netgraph_ether
 netgraph/ng_ether_echo.c	optional netgraph_ether_echo
 netgraph/ng_frame_relay.c	optional netgraph_frame_relay
 netgraph/ng_gif.c		optional netgraph_gif inet6 | netgraph_gif inet
 netgraph/ng_gif_demux.c		optional netgraph_gif_demux
 netgraph/ng_hole.c		optional netgraph_hole
 netgraph/ng_iface.c		optional netgraph_iface
 netgraph/ng_ip_input.c		optional netgraph_ip_input
 netgraph/ng_ipfw.c		optional netgraph_ipfw inet ipfirewall
 netgraph/ng_ksocket.c		optional netgraph_ksocket
 netgraph/ng_l2tp.c		optional netgraph_l2tp
 netgraph/ng_lmi.c		optional netgraph_lmi
 netgraph/ng_macfilter.c		optional netgraph_macfilter
 netgraph/ng_mppc.c		optional netgraph_mppc_compression | \
 					 netgraph_mppc_encryption
 netgraph/ng_nat.c		optional netgraph_nat inet libalias
 netgraph/ng_one2many.c		optional netgraph_one2many
 netgraph/ng_parse.c		optional netgraph
 netgraph/ng_patch.c		optional netgraph_patch
 netgraph/ng_pipe.c		optional netgraph_pipe
 netgraph/ng_ppp.c		optional netgraph_ppp
 netgraph/ng_pppoe.c		optional netgraph_pppoe
 netgraph/ng_pptpgre.c		optional netgraph_pptpgre
 netgraph/ng_pred1.c		optional netgraph_pred1
 netgraph/ng_rfc1490.c		optional netgraph_rfc1490
 netgraph/ng_socket.c		optional netgraph_socket
 netgraph/ng_split.c		optional netgraph_split
 netgraph/ng_tag.c		optional netgraph_tag
 netgraph/ng_tcpmss.c		optional netgraph_tcpmss
 netgraph/ng_tee.c		optional netgraph_tee
 netgraph/ng_tty.c		optional netgraph_tty
 netgraph/ng_vjc.c		optional netgraph_vjc
 netgraph/ng_vlan.c		optional netgraph_vlan
 netgraph/ng_vlan_rotate.c	optional netgraph_vlan_rotate
 netinet/accf_data.c		optional accept_filter_data inet
 netinet/accf_dns.c		optional accept_filter_dns inet
 netinet/accf_http.c		optional accept_filter_http inet
 netinet/if_ether.c		optional inet ether
 netinet/igmp.c			optional inet
 netinet/in.c			optional inet
 netinet/in_cksum.c		optional inet | inet6
 netinet/in_debug.c		optional inet ddb
 netinet/in_kdtrace.c		optional inet | inet6
 netinet/ip_carp.c		optional inet carp | inet6 carp
 netinet/in_fib.c		optional inet
 netinet/in_fib_algo.c		optional inet fib_algo
 netinet/in_gif.c		optional gif inet | netgraph_gif inet
 netinet/ip_gre.c		optional gre inet
 netinet/ip_id.c			optional inet
 netinet/in_jail.c		optional inet
 netinet/in_mcast.c		optional inet
 netinet/in_pcb.c		optional inet | inet6
 netinet/in_prot.c		optional inet | inet6
 netinet/in_proto.c		optional inet | inet6
 netinet/in_rmx.c		optional inet
 netinet/in_rss.c		optional inet rss
 netinet/ip_divert.c		optional ipdivert inet | ipdivert inet6
 netinet/ip_ecn.c		optional inet | inet6
 netinet/ip_encap.c		optional inet | inet6
 netinet/ip_fastfwd.c		optional inet
 netinet/ip_icmp.c		optional inet | inet6
 netinet/ip_input.c		optional inet
 netinet/ip_mroute.c		optional mrouting inet
 netinet/ip_options.c		optional inet
 netinet/ip_output.c		optional inet
 netinet/ip_reass.c		optional inet
 netinet/raw_ip.c		optional inet | inet6
 netinet/cc/cc.c			optional cc_newreno inet | cc_vegas inet | \
 	cc_htcp inet | cc_hd inet | cc_dctcp inet | cc_cubic inet | \
 	cc_chd inet | cc_cdg inet | cc_newreno inet6 | cc_vegas inet6 | \
 	cc_htcp inet6 | cc_hd inet6 |cc_dctcp inet6 | cc_cubic inet6 | \
 	cc_chd inet6 | cc_cdg inet6
 netinet/cc/cc_cdg.c		optional inet cc_cdg tcp_hhook
 netinet/cc/cc_chd.c		optional inet cc_chd tcp_hhook
 netinet/cc/cc_cubic.c		optional inet cc_cubic | inet6 cc_cubic
 netinet/cc/cc_dctcp.c		optional inet cc_dctcp | inet6 cc_dctcp
 netinet/cc/cc_hd.c		optional inet cc_hd tcp_hhook
 netinet/cc/cc_htcp.c		optional inet cc_htcp | inet6 cc_htcp
 netinet/cc/cc_newreno.c		optional inet cc_newreno | inet6 cc_newreno
 netinet/cc/cc_vegas.c		optional inet cc_vegas tcp_hhook
 netinet/khelp/h_ertt.c		optional inet tcp_hhook
 netinet/sctp_asconf.c		optional inet sctp | inet6 sctp
 netinet/sctp_auth.c		optional inet sctp | inet6 sctp
 netinet/sctp_bsd_addr.c		optional inet sctp | inet6 sctp
 netinet/sctp_cc_functions.c	optional inet sctp | inet6 sctp
 netinet/sctp_crc32.c		optional inet | inet6
 netinet/sctp_indata.c		optional inet sctp | inet6 sctp
 netinet/sctp_input.c		optional inet sctp | inet6 sctp
 netinet/sctp_kdtrace.c		optional inet sctp | inet6 sctp
 netinet/sctp_module.c		optional inet sctp | inet6 sctp
 netinet/sctp_output.c		optional inet sctp | inet6 sctp
 netinet/sctp_pcb.c		optional inet sctp | inet6 sctp
 netinet/sctp_peeloff.c		optional inet sctp | inet6 sctp
 netinet/sctp_ss_functions.c	optional inet sctp | inet6 sctp
 netinet/sctp_syscalls.c		optional inet sctp | inet6 sctp
 netinet/sctp_sysctl.c		optional inet sctp | inet6 sctp
 netinet/sctp_timer.c		optional inet sctp | inet6 sctp
 netinet/sctp_usrreq.c		optional inet sctp | inet6 sctp
 netinet/sctputil.c		optional inet sctp | inet6 sctp
 netinet/siftr.c			optional inet siftr alq | inet6 siftr alq
 netinet/tcp_ecn.c		optional inet | inet6
 netinet/tcp_fastopen.c		optional inet tcp_rfc7413 | inet6 tcp_rfc7413
 netinet/tcp_hostcache.c		optional inet | inet6
 netinet/tcp_input.c		optional inet | inet6
 netinet/tcp_log_buf.c		optional tcp_blackbox inet | tcp_blackbox inet6
 netinet/tcp_lro.c		optional inet | inet6
 netinet/tcp_output.c		optional inet | inet6
 netinet/tcp_offload.c		optional tcp_offload inet | tcp_offload inet6
 netinet/tcp_hpts.c		optional tcphpts inet | tcphpts inet6
 netinet/tcp_ratelimit.c		optional ratelimit inet | ratelimit inet6
 netinet/tcp_pcap.c		optional inet tcppcap | inet6 tcppcap \
 	compile-with "${NORMAL_C} ${NO_WNONNULL}"
 netinet/tcp_reass.c		optional inet | inet6
 netinet/tcp_sack.c		optional inet | inet6
 netinet/tcp_stacks/bbr.c	optional inet tcp_bbr | inet6 tcp_bbr \
 	compile-with "${NORMAL_C} -DMODNAME=tcp_bbr -DSTACKNAME=bbr"
 netinet/tcp_stacks/rack.c	optional inet tcp_bbr | inet6 tcp_bbr \
 	compile-with "${NORMAL_C} -DMODNAME=tcp_rack -DSTACKNAME=rack"
 netinet/tcp_stacks/rack_bbr_common.c	optional inet tcp_bbr | inet tcp_rack | inet6 tcp_bbr | inet6 tcp_rack
 netinet/tcp_stacks/sack_filter.c	optional inet tcp_bbr | inet tcp_rack | inet6 tcp_bbr | inet6 tcp_rack
 netinet/tcp_stacks/tailq_hash.c	optional inet tcp_bbr | inet tcp_rack | inet6 tcp_bbr | inet6 tcp_rack
 netinet/tcp_stats.c		optional stats inet | stats inet6
 netinet/tcp_subr.c		optional inet | inet6
 netinet/tcp_syncache.c		optional inet | inet6
 netinet/tcp_timer.c		optional inet | inet6
 netinet/tcp_timewait.c		optional inet | inet6
 netinet/tcp_usrreq.c		optional inet | inet6
 netinet/udp_usrreq.c		optional inet | inet6
 netinet/libalias/alias.c	optional libalias inet | netgraph_nat inet
 netinet/libalias/alias_db.c	optional libalias inet | netgraph_nat inet
 netinet/libalias/alias_mod.c	optional libalias | netgraph_nat
 netinet/libalias/alias_proxy.c	optional libalias inet | netgraph_nat inet
 netinet/libalias/alias_util.c	optional libalias inet | netgraph_nat inet
 netinet/libalias/alias_sctp.c	optional libalias inet | netgraph_nat inet
 netinet/netdump/netdump_client.c optional inet debugnet netdump
 netinet6/dest6.c		optional inet6
 netinet6/frag6.c		optional inet6
 netinet6/icmp6.c		optional inet6
 netinet6/in6.c			optional inet6
 netinet6/in6_cksum.c		optional inet6
 netinet6/in6_fib.c		optional inet6
 netinet6/in6_fib_algo.c		optional inet6 fib_algo
 netinet6/in6_gif.c		optional gif inet6 | netgraph_gif inet6
 netinet6/in6_ifattach.c		optional inet6
 netinet6/in6_jail.c		optional inet6
 netinet6/in6_mcast.c		optional inet6
 netinet6/in6_pcb.c		optional inet6
 netinet6/in6_proto.c		optional inet6
 netinet6/in6_rmx.c		optional inet6
 netinet6/in6_rss.c		optional inet6 rss
 netinet6/in6_src.c		optional inet6
 netinet6/ip6_fastfwd.c		optional inet6
 netinet6/ip6_forward.c		optional inet6
 netinet6/ip6_gre.c		optional gre inet6
 netinet6/ip6_id.c		optional inet6
 netinet6/ip6_input.c		optional inet6
 netinet6/ip6_mroute.c		optional mrouting inet6
 netinet6/ip6_output.c		optional inet6
 netinet6/mld6.c			optional inet6
 netinet6/nd6.c			optional inet6
 netinet6/nd6_nbr.c		optional inet6
 netinet6/nd6_rtr.c		optional inet6
 netinet6/raw_ip6.c		optional inet6
 netinet6/route6.c		optional inet6
 netinet6/scope6.c		optional inet6
 netinet6/sctp6_usrreq.c		optional inet6 sctp
 netinet6/udp6_usrreq.c		optional inet6
 netipsec/ipsec.c		optional ipsec inet | ipsec inet6
 netipsec/ipsec_input.c		optional ipsec inet | ipsec inet6
 netipsec/ipsec_mbuf.c		optional ipsec inet | ipsec inet6
 netipsec/ipsec_mod.c		optional ipsec inet | ipsec inet6
 netipsec/ipsec_output.c		optional ipsec inet | ipsec inet6
 netipsec/ipsec_pcb.c		optional ipsec inet | ipsec inet6 | \
 	ipsec_support inet | ipsec_support inet6
 netipsec/key.c			optional ipsec inet | ipsec inet6 | \
 	ipsec_support inet | ipsec_support inet6
 netipsec/key_debug.c		optional ipsec inet | ipsec inet6 | \
 	ipsec_support inet | ipsec_support inet6
 netipsec/keysock.c		optional ipsec inet | ipsec inet6 | \
 	ipsec_support inet | ipsec_support inet6
 netipsec/subr_ipsec.c		optional ipsec inet | ipsec inet6 | \
 	ipsec_support inet | ipsec_support inet6
 netipsec/udpencap.c		optional ipsec inet
 netipsec/xform_ah.c		optional ipsec inet | ipsec inet6
 netipsec/xform_esp.c		optional ipsec inet | ipsec inet6
 netipsec/xform_ipcomp.c		optional ipsec inet | ipsec inet6
 netipsec/xform_tcp.c		optional ipsec inet tcp_signature | \
 	 ipsec inet6 tcp_signature | ipsec_support inet tcp_signature | \
 	 ipsec_support inet6 tcp_signature
 netlink/netlink_generic_kpi.c	standard
 netlink/netlink_glue.c		standard
 netlink/netlink_message_parser.c	standard
 netlink/netlink_domain.c	optional netlink
 netlink/netlink_generic.c	optional netlink
 netlink/netlink_io.c		optional netlink
 netlink/netlink_message_writer.c	optional netlink
 netlink/netlink_module.c	optional netlink
 netlink/netlink_route.c		optional netlink
 netlink/route/iface_drivers.c	optional netlink
 netlink/route/iface.c		optional netlink
 netlink/route/neigh.c		optional netlink
 netlink/route/nexthop.c		optional netlink
 netlink/route/rt.c		optional netlink
 netpfil/ipfw/dn_aqm_codel.c	optional inet dummynet
 netpfil/ipfw/dn_aqm_pie.c	optional inet dummynet
 netpfil/ipfw/dn_heap.c		optional inet dummynet
 netpfil/ipfw/dn_sched_fifo.c	optional inet dummynet
 netpfil/ipfw/dn_sched_fq_codel.c	optional inet dummynet
 netpfil/ipfw/dn_sched_fq_pie.c	optional inet dummynet
 netpfil/ipfw/dn_sched_prio.c	optional inet dummynet
 netpfil/ipfw/dn_sched_qfq.c	optional inet dummynet
 netpfil/ipfw/dn_sched_rr.c	optional inet dummynet
 netpfil/ipfw/dn_sched_wf2q.c	optional inet dummynet
 netpfil/ipfw/ip_dummynet.c	optional inet dummynet
 netpfil/ipfw/ip_dn_io.c		optional inet dummynet
 netpfil/ipfw/ip_dn_glue.c	optional inet dummynet
 netpfil/ipfw/ip_fw2.c		optional inet ipfirewall
 netpfil/ipfw/ip_fw_bpf.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_dynamic.c	optional inet ipfirewall \
 	compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 netpfil/ipfw/ip_fw_eaction.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_log.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_pfil.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_sockopt.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_table.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_table_algo.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_table_value.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_iface.c	optional inet ipfirewall
 netpfil/ipfw/ip_fw_nat.c	optional inet ipfirewall_nat
 netpfil/ipfw/nat64/ip_fw_nat64.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nat64/nat64clat.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nat64/nat64clat_control.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nat64/nat64lsn.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64 compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 netpfil/ipfw/nat64/nat64lsn_control.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64 compile-with "${NORMAL_C} -I$S/contrib/ck/include"
 netpfil/ipfw/nat64/nat64stl.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nat64/nat64stl_control.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nat64/nat64_translate.c	optional inet inet6 ipfirewall \
 	ipfirewall_nat64
 netpfil/ipfw/nptv6/ip_fw_nptv6.c	optional inet inet6 ipfirewall \
 	ipfirewall_nptv6
 netpfil/ipfw/nptv6/nptv6.c	optional inet inet6 ipfirewall \
 	ipfirewall_nptv6
 netpfil/ipfw/pmod/ip_fw_pmod.c	optional inet ipfirewall_pmod
 netpfil/ipfw/pmod/tcpmod.c	optional inet ipfirewall_pmod
 netpfil/pf/if_pflog.c		optional pflog pf inet
 netpfil/pf/if_pfsync.c		optional pfsync pf inet
 netpfil/pf/pf.c			optional pf inet
 netpfil/pf/pf_if.c		optional pf inet
 netpfil/pf/pf_ioctl.c		optional pf inet
 netpfil/pf/pf_lb.c		optional pf inet
 netpfil/pf/pf_norm.c		optional pf inet
 netpfil/pf/pf_nl.c		optional pf inet
 netpfil/pf/pf_nv.c		optional pf inet
 netpfil/pf/pf_osfp.c		optional pf inet
 netpfil/pf/pf_ruleset.c		optional pf inet
 netpfil/pf/pf_syncookies.c	optional pf inet
 netpfil/pf/pf_table.c		optional pf inet
 netpfil/pf/pfsync_nv.c		optional pfsync pf inet
 netpfil/pf/in4_cksum.c		optional pf inet
 netsmb/smb_conn.c		optional netsmb
 netsmb/smb_crypt.c		optional netsmb
 netsmb/smb_dev.c		optional netsmb
 netsmb/smb_iod.c		optional netsmb
 netsmb/smb_rq.c			optional netsmb
 netsmb/smb_smb.c		optional netsmb
 netsmb/smb_subr.c		optional netsmb
 netsmb/smb_trantcp.c		optional netsmb
 netsmb/smb_usr.c		optional netsmb
 nfs/bootp_subr.c		optional bootp nfscl
 nfs/krpc_subr.c			optional bootp nfscl
 nfs/nfs_diskless.c		optional nfscl nfs_root
 nfs/nfs_nfssvc.c		optional nfscl | nfslockd | nfsd
 nlm/nlm_advlock.c		optional nfslockd | nfsd
 nlm/nlm_prot_clnt.c		optional nfslockd | nfsd
 nlm/nlm_prot_impl.c		optional nfslockd | nfsd
 nlm/nlm_prot_server.c		optional nfslockd | nfsd
 nlm/nlm_prot_svc.c		optional nfslockd | nfsd
 nlm/nlm_prot_xdr.c		optional nfslockd | nfsd
 nlm/sm_inter_xdr.c		optional nfslockd | nfsd
 
 # Linux Kernel Programming Interface
 compat/linuxkpi/common/src/linux_80211.c	optional compat_linuxkpi wlan \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_80211_macops.c	optional compat_linuxkpi wlan \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_kmod.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_acpi.c		optional compat_linuxkpi acpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_compat.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_current.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_devres.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_dmi.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_domain.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_firmware.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_fpu.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_hrtimer.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_i2c.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_i2cbb.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_interrupt.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_kthread.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_lock.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_mhi.c		optional compat_linuxkpi wlan \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_netdev.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_page.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_pci.c		optional compat_linuxkpi pci \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_tasklet.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_idr.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_radix.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_rcu.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C} -I$S/contrib/ck/include"
 compat/linuxkpi/common/src/linux_schedule.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_shmemfs.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_shrinker.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_skbuff.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_slab.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_usb.c		optional compat_linuxkpi usb \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_work.c		optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_xarray.c	optional compat_linuxkpi \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/lkpi_iic_if.m	optional compat_linuxkpi
 
 compat/linuxkpi/common/src/linux_seq_file.c	optional compat_linuxkpi | lindebugfs \
 	compile-with "${LINUXKPI_C}"
 compat/linuxkpi/common/src/linux_simple_attr.c	optional compat_linuxkpi | lindebugfs \
 	compile-with "${LINUXKPI_C}"
 compat/lindebugfs/lindebugfs.c			optional lindebugfs \
 	compile-with "${LINUXKPI_C}"
 
 # OpenFabrics Enterprise Distribution (Infiniband)
 net/if_infiniband.c					optional ofed | lagg
 ofed/drivers/infiniband/core/ib_addr.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_agent.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_cache.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_cm.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_cma.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_core_uverbs.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_cq.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_device.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_fmr_pool.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_iwcm.c			optional ofed	\
 	compile-with "${OFED_C} ${NO_WUNUSED_BUT_SET_VARIABLE}"
 ofed/drivers/infiniband/core/ib_iwpm_msg.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_iwpm_util.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_mad.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_mad_rmpp.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_multicast.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_packer.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_rdma_core.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_roce_gid_mgmt.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_sa_query.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_smi.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_sysfs.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_ucm.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_ucma.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_ud_header.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_umem.c			optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_user_mad.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_cmd.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_ioctl.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_main.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_marshall.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_async_fd.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_counters.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_cq.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_device.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_dm.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_flow_action.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_std_types_mr.c	optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_uverbs_uapi.c		optional ofed	\
 	compile-with "${OFED_C}"
 ofed/drivers/infiniband/core/ib_verbs.c			optional ofed	\
 	compile-with "${OFED_C}"
 
 ofed/drivers/infiniband/ulp/ipoib/ipoib_cm.c	optional ipoib		\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 #ofed/drivers/infiniband/ulp/ipoib/ipoib_fs.c	optional ipoib		\
 #	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c	optional ipoib		\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c	optional ipoib		\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	optional ipoib	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 ofed/drivers/infiniband/ulp/ipoib/ipoib_verbs.c	optional ipoib		\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 #ofed/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	optional ipoib		\
 #	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/"
 
 ofed/drivers/infiniband/ulp/sdp/sdp_bcopy.c	optional sdp inet	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/"
 ofed/drivers/infiniband/ulp/sdp/sdp_main.c	optional sdp inet 	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/"
 ofed/drivers/infiniband/ulp/sdp/sdp_rx.c	optional sdp inet 	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/ ${NO_WUNUSED_BUT_SET_VARIABLE}"
 ofed/drivers/infiniband/ulp/sdp/sdp_cma.c	optional sdp inet 	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/"
 ofed/drivers/infiniband/ulp/sdp/sdp_tx.c	optional sdp inet 	\
 	compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/ ${NO_WUNUSED_BUT_SET_VARIABLE}"
 
 dev/irdma/icrdma.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_cm.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_ctrl.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_hmc.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_hw.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/icrdma_hw.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/fbsd_kcompat.c	optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_kcompat.c	optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_pble.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_puda.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_uda.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_uk.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_utils.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_verbs.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 dev/irdma/irdma_ws.c		optional irdma ice inet inet6 pci ofed \
 	compile-with "${OFED_C} -I$S/dev/ice/"
 
 dev/mthca/mthca_allocator.c		optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_av.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_catas.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_cmd.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_cq.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_eq.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_mad.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_main.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_mcg.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_memfree.c		optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_mr.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_pd.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_profile.c		optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_provider.c		optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_qp.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_reset.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_srq.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 dev/mthca/mthca_uar.c			optional mthca pci ofed \
 	compile-with "${OFED_C}"
 
 dev/mlx4/mlx4_ib/mlx4_ib_alias_GUID.c		optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_mcg.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_sysfs.c		optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_cm.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_ah.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_cq.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_doorbell.c		optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_mad.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_main.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_mr.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_qp.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_srq.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_ib/mlx4_ib_wc.c			optional mlx4ib pci ofed \
 	compile-with "${OFED_C}"
 
 dev/mlx4/mlx4_core/mlx4_alloc.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_catas.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_cmd.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_cq.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_eq.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_fw.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_fw_qos.c		optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_icm.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_intf.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_main.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_mcg.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_mr.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_pd.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_port.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_profile.c		optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_qp.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_reset.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_sense.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_srq.c			optional mlx4 pci \
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_core/mlx4_resource_tracker.c	optional mlx4 pci \
 	compile-with "${OFED_C}"
 
 dev/mlx4/mlx4_en/mlx4_en_cq.c			optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_main.c			optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_netdev.c		optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_port.c			optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_resources.c		optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_rx.c			optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx4/mlx4_en/mlx4_en_tx.c			optional mlx4en pci inet inet6	\
 	compile-with "${OFED_C}"
 
 dev/mlx5/mlx5_ib/mlx5_ib_ah.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_cong.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_cq.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_devx.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_doorbell.c		optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_gsi.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_mad.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_main.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_mem.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_mr.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_qp.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_srq.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_ib/mlx5_ib_virt.c			optional mlx5ib pci ofed \
 	compile-with "${OFED_C}"
 
 dev/mlx5/mlx5_core/mlx5_alloc.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_cmd.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_cq.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_diag_cnt.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_diagnostics.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_eq.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_eswitch.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fs_cmd.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fs_tcp.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fs_tree.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fw.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fwdump.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_health.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_mad.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_main.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_mcg.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_mpfs.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_mr.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_pagealloc.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_pd.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_port.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_qp.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_rl.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_srq.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_tls.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_transobj.c		optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_uar.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_vport.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_vsc.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_wq.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_lib/mlx5_gid.c			optional mlx5 pci	\
 	compile-with "${OFED_C}"
 
 dev/mlx5/mlx5_en/mlx5_en_dim.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_ethtool.c		optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_main.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_tx.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_flow_table.c		optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_hw_tls.c		optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c		optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_iq.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_rx.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_rl.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_txrx.c			optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 dev/mlx5/mlx5_en/mlx5_en_port_buffer.c		optional mlx5en pci inet inet6	\
 	compile-with "${OFED_C}"
 
 # crypto support
 opencrypto/cbc_mac.c		optional crypto
 opencrypto/criov.c		optional crypto
 opencrypto/crypto.c		optional crypto
 opencrypto/cryptodev.c		optional cryptodev
 opencrypto/cryptodev_if.m	optional crypto
 opencrypto/cryptosoft.c		optional crypto
 opencrypto/cryptodeflate.c	optional crypto
 opencrypto/gmac.c		optional crypto
 opencrypto/gfmult.c		optional crypto
 opencrypto/ktls_ocf.c		optional kern_tls
 opencrypto/rmd160.c		optional crypto
 opencrypto/xform_aes_cbc.c	optional crypto
 opencrypto/xform_aes_icm.c	optional crypto
 opencrypto/xform_aes_xts.c	optional crypto
 opencrypto/xform_cbc_mac.c	optional crypto
 opencrypto/xform_chacha20_poly1305.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 opencrypto/xform_cml.c		optional crypto
 opencrypto/xform_deflate.c	optional crypto
 opencrypto/xform_gmac.c		optional crypto
 opencrypto/xform_null.c		optional crypto
 opencrypto/xform_poly1305.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 opencrypto/xform_rmd160.c	optional crypto
 opencrypto/xform_sha1.c		optional crypto
 opencrypto/xform_sha2.c		optional crypto
 contrib/libsodium/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium -Wno-unused-function"
 contrib/libsodium/src/libsodium/crypto_core/hchacha20/core_hchacha20.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_scalarmult/curve25519/scalarmult_curve25519.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium -Wno-unused-function"
 contrib/libsodium/src/libsodium/crypto_stream/chacha20/stream_chacha20.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_stream/chacha20/ref/chacha20_ref.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 contrib/libsodium/src/libsodium/crypto_verify/sodium/verify.c \
 	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include/sodium -I$S/crypto/libsodium"
 crypto/libsodium/randombytes.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 crypto/libsodium/utils.c	optional crypto \
 	compile-with "${NORMAL_C} -I$S/contrib/libsodium/src/libsodium/include -I$S/crypto/libsodium"
 
 rpc/auth_none.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/auth_unix.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/authunix_prot.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/clnt_bck.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/clnt_dg.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/clnt_rc.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/clnt_vc.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/getnetconfig.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/replay.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/rpc_callmsg.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/rpc_generic.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/rpc_prot.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/rpcb_clnt.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/rpcb_prot.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/svc.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_auth.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_auth_unix.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_dg.c			optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_generic.c		optional krpc | nfslockd | nfscl | nfsd
 rpc/svc_vc.c			optional krpc | nfslockd | nfscl | nfsd
 #
 # Kernel RPC-over-TLS
 #
 rpctlscd.h			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x"			\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -hM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v pthread.h > rpctlscd.h" \
 	no-obj no-implicit-rule before-depend local			\
 	clean			"rpctlscd.h"
 rpctlscd_xdr.c			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x rpctlscd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -c $S/rpc/rpcsec_tls/rpctlscd.x -o rpctlscd_xdr.c" no-ctfconvert \
 	no-implicit-rule before-depend local				\
 	clean			"rpctlscd_xdr.c"
 rpctlscd_clnt.c			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlscd.x rpctlscd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -lM $S/rpc/rpcsec_tls/rpctlscd.x | grep -v string.h > rpctlscd_clnt.c" no-ctfconvert \
 	no-implicit-rule before-depend local				\
 	clean			"rpctlscd_clnt.c"
 rpctlssd.h			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x"			\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -hM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v pthread.h > rpctlssd.h" \
 	no-obj no-implicit-rule before-depend local			\
 	clean			"rpctlssd.h"
 rpctlssd_xdr.c			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x rpctlssd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -c $S/rpc/rpcsec_tls/rpctlssd.x -o rpctlssd_xdr.c" no-ctfconvert \
 	no-implicit-rule before-depend local				\
 	clean			"rpctlssd_xdr.c"
 rpctlssd_clnt.c			optional krpc | nfslockd | nfscl | nfsd	\
 	dependency		"$S/rpc/rpcsec_tls/rpctlssd.x rpctlssd.h"		\
 	compile-with		"RPCGEN_CPP='${CPP}' rpcgen -lM $S/rpc/rpcsec_tls/rpctlssd.x | grep -v string.h > rpctlssd_clnt.c" no-ctfconvert \
 	no-implicit-rule before-depend local				\
 	clean			"rpctlssd_clnt.c"
 rpc/rpcsec_tls/rpctls_impl.c	optional krpc | nfslockd | nfscl | nfsd
 rpc/rpcsec_tls/auth_tls.c	optional krpc | nfslockd | nfscl | nfsd
 rpc/rpcsec_gss/rpcsec_gss.c	optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/rpcsec_gss_conf.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/rpcsec_gss_misc.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/rpcsec_gss_prot.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 rpc/rpcsec_gss/svc_rpcsec_gss.c	optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi
 security/audit/audit.c		optional audit
 security/audit/audit_arg.c	optional audit
 security/audit/audit_bsm.c	optional audit
 security/audit/audit_bsm_db.c	optional audit
 security/audit/audit_bsm_klib.c	optional audit
 security/audit/audit_dtrace.c	optional dtaudit audit | dtraceall audit compile-with "${CDDL_C}"
 security/audit/audit_pipe.c	optional audit
 security/audit/audit_syscalls.c	standard
 security/audit/audit_trigger.c	optional audit
 security/audit/audit_worker.c	optional audit
 security/audit/bsm_domain.c	optional audit
 security/audit/bsm_errno.c	optional audit
 security/audit/bsm_fcntl.c	optional audit
 security/audit/bsm_socket_type.c	optional audit
 security/audit/bsm_token.c	optional audit
 security/mac/mac_audit.c	optional mac audit
 security/mac/mac_cred.c		optional mac
 security/mac/mac_kdb.c		optional mac
 security/mac/mac_framework.c	optional mac
 security/mac/mac_inet.c		optional mac inet | mac inet6
 security/mac/mac_inet6.c	optional mac inet6
 security/mac/mac_label.c	optional mac
 security/mac/mac_net.c		optional mac
 security/mac/mac_pipe.c		optional mac
 security/mac/mac_posix_sem.c	optional mac
 security/mac/mac_posix_shm.c	optional mac
 security/mac/mac_priv.c		optional mac
 security/mac/mac_process.c	optional mac
 security/mac/mac_socket.c	optional mac
 security/mac/mac_syscalls.c	standard
 security/mac/mac_system.c	optional mac
 security/mac/mac_sysv_msg.c	optional mac
 security/mac/mac_sysv_sem.c	optional mac
 security/mac/mac_sysv_shm.c	optional mac
 security/mac/mac_vfs.c		optional mac
 security/mac_biba/mac_biba.c	optional mac_biba
 security/mac_ddb/mac_ddb.c	optional mac_ddb
 security/mac_bsdextended/mac_bsdextended.c	optional mac_bsdextended
 security/mac_bsdextended/ugidfw_system.c	optional mac_bsdextended
 security/mac_bsdextended/ugidfw_vnode.c		optional mac_bsdextended
 security/mac_ifoff/mac_ifoff.c	optional mac_ifoff
 security/mac_ipacl/mac_ipacl.c	optional mac_ipacl
 security/mac_lomac/mac_lomac.c	optional mac_lomac
 security/mac_mls/mac_mls.c	optional mac_mls
 security/mac_none/mac_none.c	optional mac_none
 security/mac_ntpd/mac_ntpd.c	optional mac_ntpd
 security/mac_partition/mac_partition.c optional mac_partition
 security/mac_portacl/mac_portacl.c optional mac_portacl
 security/mac_priority/mac_priority.c	optional mac_priority
 security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids
 security/mac_stub/mac_stub.c	optional mac_stub
 security/mac_test/mac_test.c	optional mac_test
 security/mac_grantbylabel/mac_grantbylabel.c		optional mac_grantbylabel
 security/mac_veriexec/mac_veriexec.c			optional mac_veriexec
 security/mac_veriexec/veriexec_fingerprint.c		optional mac_veriexec
 security/mac_veriexec/veriexec_metadata.c		optional mac_veriexec
 security/mac_veriexec_parser/mac_veriexec_parser.c	optional mac_veriexec mac_veriexec_parser
 security/mac_veriexec/mac_veriexec_rmd160.c		optional mac_veriexec_rmd160
 security/mac_veriexec/mac_veriexec_sha1.c		optional mac_veriexec_sha1
 security/mac_veriexec/mac_veriexec_sha256.c		optional mac_veriexec_sha256
 security/mac_veriexec/mac_veriexec_sha384.c		optional mac_veriexec_sha384
 security/mac_veriexec/mac_veriexec_sha512.c		optional mac_veriexec_sha512
 teken/teken.c			optional sc !SC_NO_TERM_TEKEN | vt
 ufs/ffs/ffs_alloc.c		optional ffs
 ufs/ffs/ffs_balloc.c		optional ffs
 ufs/ffs/ffs_inode.c		optional ffs
 ufs/ffs/ffs_snapshot.c		optional ffs
 ufs/ffs/ffs_softdep.c		optional ffs
 ufs/ffs/ffs_subr.c		optional ffs | geom_label
 ufs/ffs/ffs_tables.c		optional ffs | geom_label
 ufs/ffs/ffs_vfsops.c		optional ffs
 ufs/ffs/ffs_vnops.c		optional ffs
 ufs/ffs/ffs_rawread.c		optional ffs directio
 ufs/ffs/ffs_suspend.c		optional ffs
 ufs/ufs/ufs_acl.c		optional ffs
 ufs/ufs/ufs_bmap.c		optional ffs
 ufs/ufs/ufs_dirhash.c		optional ffs
 ufs/ufs/ufs_extattr.c		optional ffs
 ufs/ufs/ufs_gjournal.c		optional ffs UFS_GJOURNAL
 ufs/ufs/ufs_inode.c		optional ffs
 ufs/ufs/ufs_lookup.c		optional ffs
 ufs/ufs/ufs_quota.c		optional ffs
 ufs/ufs/ufs_vfsops.c		optional ffs
 ufs/ufs/ufs_vnops.c		optional ffs
 vm/device_pager.c		standard
 vm/phys_pager.c			standard
 vm/redzone.c			optional DEBUG_REDZONE
 vm/sg_pager.c			standard
 vm/swap_pager.c			standard
 vm/uma_core.c			standard
 vm/uma_dbg.c			standard
 vm/memguard.c			optional DEBUG_MEMGUARD
 vm/vm_domainset.c		standard
 vm/vm_fault.c			standard
 vm/vm_glue.c			standard
 vm/vm_init.c			standard
 vm/vm_kern.c			standard
 vm/vm_map.c			standard
 vm/vm_meter.c			standard
 vm/vm_mmap.c			standard
 vm/vm_object.c			standard
 vm/vm_page.c			standard
 vm/vm_pageout.c			standard
 vm/vm_pager.c			standard
 vm/vm_phys.c			standard
 vm/vm_radix.c			standard
 vm/vm_reserv.c			standard
 vm/vm_swapout.c			optional !NO_SWAPPING
 vm/vm_swapout_dummy.c		optional NO_SWAPPING
 vm/vm_unix.c			standard
 vm/vnode_pager.c		standard
 xen/features.c			optional xenhvm
 xen/xen_common.c		optional xenhvm
 xen/xenbus/xenbus_if.m		optional xenhvm
 xen/xenbus/xenbus.c		optional xenhvm
 xen/xenbus/xenbusb_if.m		optional xenhvm
 xen/xenbus/xenbusb.c		optional xenhvm
 xen/xenbus/xenbusb_front.c	optional xenhvm
 xen/xenbus/xenbusb_back.c	optional xenhvm
 xen/xenmem/xenmem_if.m		optional xenhvm
 xdr/xdr.c			optional xdr | krpc | nfslockd | nfscl | nfsd
 xdr/xdr_array.c			optional xdr | krpc | nfslockd | nfscl | nfsd
 xdr/xdr_mbuf.c			optional xdr | krpc | nfslockd | nfscl | nfsd
 xdr/xdr_mem.c			optional xdr | krpc | nfslockd | nfscl | nfsd
 xdr/xdr_reference.c		optional xdr | krpc | nfslockd | nfscl | nfsd
 xdr/xdr_sizeof.c		optional xdr | krpc | nfslockd | nfscl | nfsd
diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index 0ed96fe43c0a..9b09520b3257 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -1,869 +1,870 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #ifndef _NFS_NFS_H_
 #define	_NFS_NFS_H_
 /*
  * Tunable constants for nfs
  */
 
 #define	NFS_MAXIOVEC	34
 #define	NFS_TICKINTVL	500		/* Desired time for a tick (msec) */
 #define	NFS_HZ		(hz / nfscl_ticks) /* Ticks/sec */
 #define	NFS_TIMEO	(1 * NFS_HZ)	/* Default timeout = 1 second */
 #define	NFS_MINTIMEO	(1 * NFS_HZ)	/* Min timeout to use */
 #define	NFS_MAXTIMEO	(60 * NFS_HZ)	/* Max timeout to backoff to */
 #define	NFS_TCPTIMEO	300		/* TCP timeout */
 #define	NFS_MAXRCVTIMEO	60		/* 1 minute in seconds */
 #define	NFS_MINIDEMTIMEO (5 * NFS_HZ)	/* Min timeout for non-idempotent ops*/
 #define	NFS_MAXREXMIT	100		/* Stop counting after this many */
 #define	NFSV4_CALLBACKTIMEO 800		/* Timeout in msec */
 #define	NFSV4_CALLBACKRETRY 5		/* Number of retries before failure */
 #define	NFSV4_SLOTS	64		/* Number of slots, fore channel */
 #define	NFSV4_CBSLOTS	8		/* Number of slots, back channel */
 #define	NFSV4_CBRETRYCNT 4		/* # of CBRecall retries upon err */
 #define	NFSV4_UPCALLTIMEO (15 * NFS_HZ)	/* Timeout in ticks for upcalls */
 					/* to gssd or nfsuserd */
 #define	NFSV4_UPCALLRETRY 4		/* Number of retries before failure */
 #define	NFS_MAXWINDOW	1024		/* Max number of outstanding requests */
 #define	NFS_RETRANS	10		/* Num of retrans for soft mounts */
 #define	NFS_RETRANS_TCP	2		/* Num of retrans for TCP soft mounts */
 #define	NFS_MAXGRPS	16		/* Max. size of groups list */
 #define	NFS_TRYLATERDEL	15		/* Maximum delay timeout (sec) */
 #ifndef NFS_REMOVETIMEO
 #define	NFS_REMOVETIMEO 15  /* # sec to wait for delegret in local syscall */
 #endif
 #ifndef NFS_MINATTRTIMO
 #define	NFS_MINATTRTIMO 5		/* Attribute cache timeout in sec */
 #endif
 #ifndef NFS_MAXATTRTIMO
 #define	NFS_MAXATTRTIMO 60
 #endif
 #define	NFS_WSIZE	8192		/* Def. write data size <= 8192 */
 #define	NFS_RSIZE	8192		/* Def. read data size <= 8192 */
 #define	NFS_READDIRSIZE	8192		/* Def. readdir size */
 #define	NFS_DEFRAHEAD	1		/* Def. read ahead # blocks */
 #define	NFS_MAXRAHEAD	16		/* Max. read ahead # blocks */
 #define	NFS_MAXASYNCDAEMON 	64	/* Max. number async_daemons runnable */
 #define	NFS_MAXUIDHASH	64		/* Max. # of hashed uid entries/mp */
 #ifndef	NFSRV_LEASE
 #define	NFSRV_LEASE		120	/* Lease time in seconds for V4 */
 #endif					/* assigned to nfsrv_lease */
 #ifndef NFSRV_STALELEASE
 #define	NFSRV_STALELEASE	(5 * nfsrv_lease)
 #endif
 #ifndef NFSRV_MOULDYLEASE
 #define	NFSRV_MOULDYLEASE	604800	/* One week (in sec) */
 #endif
 #ifndef NFSCLIENTHASHSIZE
 #define	NFSCLIENTHASHSIZE	20	/* Size of server client hash table */
 #endif
 #ifndef NFSLOCKHASHSIZE
 #define	NFSLOCKHASHSIZE		20	/* Size of server nfslock hash table */
 #endif
 #ifndef NFSSESSIONHASHSIZE
 #define	NFSSESSIONHASHSIZE	20	/* Size of server session hash table */
 #endif
 #define	NFSSTATEHASHSIZE	10	/* Size of server stateid hash table */
 #define	NFSLAYOUTHIGHWATER	1000000	/* Upper limit for # of layouts */
 #ifndef	NFSCLDELEGHIGHWATER
 #define	NFSCLDELEGHIGHWATER	10000	/* limit for client delegations */
 #endif
 #ifndef	NFSCLLAYOUTHIGHWATER
 #define	NFSCLLAYOUTHIGHWATER	10000	/* limit for client pNFS layouts */
 #endif
 #ifndef NFSNOOPEN			/* Inactive open owner (sec) */
 #define	NFSNOOPEN		120
 #endif
 #define	NFSRV_LEASEDELTA	15	/* # of seconds to delay beyond lease */
 #define	NFS_IDMAXSIZE		4	/* max sizeof (in_addr_t) */
 #ifndef NFSRVCACHE_UDPTIMEOUT
 #define	NFSRVCACHE_UDPTIMEOUT	30	/* # of sec to hold cached rpcs(udp) */
 #endif
 #ifndef NFSRVCACHE_UDPHIGHWATER
 #define	NFSRVCACHE_UDPHIGHWATER	500	/* Max # of udp cache entries */
 #endif
 #ifndef NFSRVCACHE_TCPTIMEOUT
 #define	NFSRVCACHE_TCPTIMEOUT	(3600*12) /*#of sec to hold cached rpcs(tcp) */
 #endif
 #ifndef	NFSRVCACHE_FLOODLEVEL
 #define	NFSRVCACHE_FLOODLEVEL	16384	/* Very high water mark for cache */
 #endif
 #ifndef	NFSRV_CLIENTHIGHWATER
 #define	NFSRV_CLIENTHIGHWATER	1000
 #endif
 #ifndef	NFSRV_MAXDUMPLIST
 #define	NFSRV_MAXDUMPLIST	10000
 #endif
 #ifndef NFS_ACCESSCACHESIZE
 #define	NFS_ACCESSCACHESIZE	8
 #endif
 #define	NFSV4_CBPORT	7745		/* Callback port for testing */
 
 /*
  * This macro defines the high water mark for issuing V4 delegations.
  * (It is currently set at a conservative 20% of nfsrv_v4statelimit. This
  *  may want to increase when clients can make more effective use of
  *  delegations.)
  */
 #define	NFSRV_V4DELEGLIMIT(c) (((c) * 5) > nfsrv_v4statelimit)
 
 #define	NFS_READDIRBLKSIZ	DIRBLKSIZ	/* Minimal nm_readdirsize */
 
 /*
  * The NFSv4 RFCs do not define an upper limit on the length of Owner and
  * OwnerGroup strings.  Since FreeBSD handles a group name > 1024bytes in
  * length, set a generous sanity limit of 10Kbytes.
  */
 #define	NFSV4_MAXOWNERGROUPLEN	(10 * 1024)
 
 /*
  * Oddballs
  */
 #define	NFS_CMPFH(n, f, s) 						\
     ((n)->n_fhp->nfh_len == (s) && !NFSBCMP((n)->n_fhp->nfh_fh, (caddr_t)(f), (s)))
 #define	NFSRV_CMPFH(nf, ns, f, s) 					\
 	((ns) == (s) && !NFSBCMP((caddr_t)(nf), (caddr_t)(f), (s)))
 #define	NFS_CMPTIME(t1, t2) 						\
 	((t1).tv_sec == (t2).tv_sec && (t1).tv_nsec == (t2).tv_nsec)
 #define	NFS_SETTIME(t) do { 						\
 	(t).tv_sec = time.tv_sec; (t).tv_nsec = 1000 * time.tv_usec; } while (0)
 #define	NFS_SRVMAXDATA(n) 						\
 		(((n)->nd_flag & (ND_NFSV3 | ND_NFSV4)) ? 		\
 		 nfs_srvmaxio : NFS_V2MAXDATA)
 #define	NFS64BITSSET	0xffffffffffffffffull
 #define	NFS64BITSMINUS1	0xfffffffffffffffeull
 
 /*
  * Structures for the nfssvc(2) syscall. Not that anyone but nfsd, mount_nfs
  * and nfsloaduser should ever try and use it.
  */
 struct nfsd_addsock_args {
 	int	sock;		/* Socket to serve */
 	caddr_t	name;		/* Client addr for connection based sockets */
 	int	namelen;	/* Length of name */
 };
 
 /*
  * nfsd argument for new krpc.
  * (New version supports pNFS, indicated by NFSSVC_NEWSTRUCT flag.)
  */
 struct nfsd_nfsd_args {
 	const char *principal;	/* GSS-API service principal name */
 	int	minthreads;	/* minimum service thread count */
 	int	maxthreads;	/* maximum service thread count */
 	int	version;	/* Allow multiple variants */
 	char	*addr;		/* pNFS DS addresses */
 	int	addrlen;	/* Length of addrs */
 	char	*dnshost;	/* DNS names for DS addresses */
 	int	dnshostlen;	/* Length of DNS names */
 	char	*dspath;	/* DS Mount path on MDS */
 	int	dspathlen;	/* Length of DS Mount path on MDS */
 	char	*mdspath;	/* MDS mount for DS path on MDS */
 	int	mdspathlen;	/* Length of MDS mount for DS path on MDS */
 	int	mirrorcnt;	/* Number of mirrors to create on DSs */
 };
 
 /*
  * NFSDEV_MAXMIRRORS - Maximum level of mirroring for a DS.
  * (Most will only put files on two DSs, but this setting allows up to 4.)
  * NFSDEV_MAXVERS - maximum number of NFS versions supported by Flex File.
  */
 #define	NFSDEV_MAXMIRRORS	4
 #define	NFSDEV_MAXVERS		4
 
 struct nfsd_pnfsd_args {
 	int	op;		/* Which pNFSd op to perform. */
 	char	*mdspath;	/* Path of MDS file. */
 	char	*dspath;	/* Path of recovered DS mounted on dir. */
 	char	*curdspath;	/* Path of current DS mounted on dir. */
 };
 
 #define	PNFSDOP_DELDSSERVER	1
 #define	PNFSDOP_COPYMR		2
 #define	PNFSDOP_FORCEDELDS	3
 
 /* Old version. */
 struct nfsd_nfsd_oargs {
 	const char *principal;	/* GSS-API service principal name */
 	int	minthreads;	/* minimum service thread count */
 	int	maxthreads;	/* maximum service thread count */
 };
 
 /*
  * Arguments for use by the callback daemon.
  */
 struct nfsd_nfscbd_args {
 	const char *principal;	/* GSS-API service principal name */
 };
 
 struct nfscbd_args {
 	int	sock;		/* Socket to serve */
 	caddr_t	name;		/* Client addr for connection based sockets */
 	int	namelen;	/* Length of name */
 	u_short	port;		/* Port# for callbacks */
 };
 
 struct nfsd_idargs {
 	int		nid_flag;	/* Flags (see below) */
 	uid_t		nid_uid;	/* user/group id */
 	gid_t		nid_gid;
 	int		nid_usermax;	/* Upper bound on user name cache */
 	int		nid_usertimeout;/* User name timeout (minutes) */
 	u_char		*nid_name;	/* Name */
 	int		nid_namelen;	/* and its length */
 	gid_t		*nid_grps;	/* and the list */
 	int		nid_ngroup;	/* Size of groups list */
 };
 
 struct nfsd_oidargs {
 	int		nid_flag;	/* Flags (see below) */
 	uid_t		nid_uid;	/* user/group id */
 	gid_t		nid_gid;
 	int		nid_usermax;	/* Upper bound on user name cache */
 	int		nid_usertimeout;/* User name timeout (minutes) */
 	u_char		*nid_name;	/* Name */
 	int		nid_namelen;	/* and its length */
 };
 
 struct nfsuserd_args {
 	sa_family_t	nuserd_family;	/* Address family to use */
 	u_short		nuserd_port;	/* Port# */
 };
 
 struct nfsd_clid {
 	int		nclid_idlen;	/* Length of client id */
 	u_char		nclid_id[NFSV4_OPAQUELIMIT]; /* and name */
 };
 
 struct nfsd_dumplist {
 	int		ndl_size;	/* Number of elements */
 	void		*ndl_list;	/* and the list of elements */
 };
 
 struct nfsd_dumpclients {
 	u_int32_t	ndcl_flags;		/* LCL_xxx flags */
 	u_int32_t	ndcl_nopenowners;	/* Number of openowners */
 	u_int32_t	ndcl_nopens;		/* and opens */
 	u_int32_t	ndcl_nlockowners;	/* and of lockowners */
 	u_int32_t	ndcl_nlocks;		/* and of locks */
 	u_int32_t	ndcl_ndelegs;		/* and of delegations */
 	u_int32_t	ndcl_nolddelegs;	/* and old delegations */
 	sa_family_t	ndcl_addrfam;		/* Callback address */
 	union {
 		struct in_addr sin_addr;
 		struct in6_addr sin6_addr;
 	} ndcl_cbaddr;
 	struct nfsd_clid ndcl_clid;	/* and client id */
 };
 
 struct nfsd_dumplocklist {
 	char		*ndllck_fname;	/* File Name */
 	int		ndllck_size;	/* Number of elements */
 	void		*ndllck_list;	/* and the list of elements */
 };
 
 struct nfsd_dumplocks {
 	u_int32_t	ndlck_flags;		/* state flags NFSLCK_xxx */
 	nfsv4stateid_t	ndlck_stateid;		/* stateid */
 	u_int64_t	ndlck_first;		/* lock byte range */
 	u_int64_t	ndlck_end;
 	struct nfsd_clid ndlck_owner;		/* Owner of open/lock */
 	sa_family_t	ndlck_addrfam;		/* Callback address */
 	union {
 		struct in_addr sin_addr;
 		struct in6_addr sin6_addr;
 	} ndlck_cbaddr;
 	struct nfsd_clid ndlck_clid;	/* and client id */
 };
 
 /*
  * Structure for referral information.
  */
 struct nfsreferral {
 	u_char		*nfr_srvlist;	/* List of servers */
 	int		nfr_srvcnt;	/* number of servers */
 	vnode_t		nfr_vp;	/* vnode for referral */
 	uint64_t	nfr_dfileno;	/* assigned dir inode# */
 };
 
 /*
  * Flags for lc_flags and opsflags for nfsrv_getclient().
  */
 #define	LCL_NEEDSCONFIRM	0x00000001
 #define	LCL_DONTCLEAN		0x00000002
 #define	LCL_WAKEUPWANTED	0x00000004
 #define	LCL_TCPCALLBACK		0x00000008
 #define	LCL_CALLBACKSON		0x00000010
 #define	LCL_INDEXNOTOK		0x00000020
 #define	LCL_STAMPEDSTABLE	0x00000040
 #define	LCL_EXPIREIT		0x00000080
 #define	LCL_CBDOWN		0x00000100
 #define	LCL_KERBV		0x00000400
 #define	LCL_NAME		0x00000800
 #define	LCL_NEEDSCBNULL		0x00001000
 #define	LCL_GSSINTEGRITY	0x00002000
 #define	LCL_GSSPRIVACY		0x00004000
 #define	LCL_ADMINREVOKED	0x00008000
 #define	LCL_RECLAIMCOMPLETE	0x00010000
 #define	LCL_NFSV41		0x00020000
 #define	LCL_DONEBINDCONN	0x00040000
 #define	LCL_RECLAIMONEFS	0x00080000
 #define	LCL_NFSV42		0x00100000
 #define	LCL_TLSCB		0x00200000
 #define	LCL_MACHCRED		0x00400000
 
 #define	LCL_GSS		LCL_KERBV	/* Or of all mechs */
 
 /*
  * Bits for flags in nfslock and nfsstate.
  * The access, deny, NFSLCK_READ and NFSLCK_WRITE bits must be defined as
  * below, in the correct order, so the shifts work for tests.
  */
 #define	NFSLCK_READACCESS	0x00000001
 #define	NFSLCK_WRITEACCESS	0x00000002
 #define	NFSLCK_ACCESSBITS	(NFSLCK_READACCESS | NFSLCK_WRITEACCESS)
 #define	NFSLCK_SHIFT		2
 #define	NFSLCK_READDENY		0x00000004
 #define	NFSLCK_WRITEDENY	0x00000008
 #define	NFSLCK_DENYBITS		(NFSLCK_READDENY | NFSLCK_WRITEDENY)
 #define	NFSLCK_SHAREBITS 						\
     (NFSLCK_READACCESS|NFSLCK_WRITEACCESS|NFSLCK_READDENY|NFSLCK_WRITEDENY)
 #define	NFSLCK_LOCKSHIFT	4
 #define	NFSLCK_READ		0x00000010
 #define	NFSLCK_WRITE		0x00000020
 #define	NFSLCK_BLOCKING		0x00000040
 #define	NFSLCK_RECLAIM		0x00000080
 #define	NFSLCK_OPENTOLOCK	0x00000100
 #define	NFSLCK_TEST		0x00000200
 #define	NFSLCK_LOCK		0x00000400
 #define	NFSLCK_UNLOCK		0x00000800
 #define	NFSLCK_OPEN		0x00001000
 #define	NFSLCK_CLOSE		0x00002000
 #define	NFSLCK_CHECK		0x00004000
 #define	NFSLCK_RELEASE		0x00008000
 #define	NFSLCK_NEEDSCONFIRM	0x00010000
 #define	NFSLCK_CONFIRM		0x00020000
 #define	NFSLCK_DOWNGRADE	0x00040000
 #define	NFSLCK_DELEGREAD	0x00080000
 #define	NFSLCK_DELEGWRITE	0x00100000
 #define	NFSLCK_DELEGCUR		0x00200000
 #define	NFSLCK_DELEGPREV	0x00400000
 #define	NFSLCK_OLDDELEG		0x00800000
 #define	NFSLCK_DELEGRECALL	0x01000000
 #define	NFSLCK_SETATTR		0x02000000
 #define	NFSLCK_DELEGPURGE	0x04000000
 #define	NFSLCK_DELEGRETURN	0x08000000
 #define	NFSLCK_WANTWDELEG	0x10000000
 #define	NFSLCK_WANTRDELEG	0x20000000
 #define	NFSLCK_WANTNODELEG	0x40000000
 #define	NFSLCK_WANTBITS							\
     (NFSLCK_WANTWDELEG | NFSLCK_WANTRDELEG | NFSLCK_WANTNODELEG)
 
 /* And bits for nid_flag */
 #define	NFSID_INITIALIZE	0x0001
 #define	NFSID_ADDUID		0x0002
 #define	NFSID_DELUID		0x0004
 #define	NFSID_ADDUSERNAME	0x0008
 #define	NFSID_DELUSERNAME	0x0010
 #define	NFSID_ADDGID		0x0020
 #define	NFSID_DELGID		0x0040
 #define	NFSID_ADDGROUPNAME	0x0080
 #define	NFSID_DELGROUPNAME	0x0100
 
 /*
  * fs.nfs sysctl(3) identifiers
  */
 #define	NFS_NFSSTATS	1		/* struct: struct nfsstats */
 
 /*
  * Here is the definition of the attribute bits array and macros that
  * manipulate it.
  * THE MACROS MUST BE MANUALLY MODIFIED IF NFSATTRBIT_MAXWORDS CHANGES!!
  * It is (NFSATTRBIT_MAX + 31) / 32.
  */
 #define	NFSATTRBIT_MAXWORDS	3
 
 typedef struct {
 	u_int32_t bits[NFSATTRBIT_MAXWORDS];
 } nfsattrbit_t;
 
 #define	NFSZERO_ATTRBIT(b) do {						\
 	(b)->bits[0] = 0;						\
 	(b)->bits[1] = 0;						\
 	(b)->bits[2] = 0;						\
 } while (0)
 
 #define	NFSSET_ATTRBIT(t, f) do {					\
 	(t)->bits[0] = (f)->bits[0];			 		\
 	(t)->bits[1] = (f)->bits[1];					\
 	(t)->bits[2] = (f)->bits[2];					\
 } while (0)
 
 #define	NFSSETSUPP_ATTRBIT(b, n) do { 					\
 	(b)->bits[0] = NFSATTRBIT_SUPP0; 				\
 	(b)->bits[1] = (NFSATTRBIT_SUPP1 | NFSATTRBIT_SUPPSETONLY1);	\
 	(b)->bits[2] = (NFSATTRBIT_SUPP2 | NFSATTRBIT_SUPPSETONLY2);	\
 	if (((n)->nd_flag & ND_NFSV41) == 0) {				\
 		(b)->bits[1] &= ~NFSATTRBIT_NFSV41_1;			\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV41_2;			\
 	}								\
 	if (((n)->nd_flag & ND_NFSV42) == 0)				\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV42_2;			\
 } while (0)
 
 #define	NFSISSET_ATTRBIT(b, p)	((b)->bits[(p) / 32] & (1 << ((p) % 32)))
 #define	NFSSETBIT_ATTRBIT(b, p)	((b)->bits[(p) / 32] |= (1 << ((p) % 32)))
 #define	NFSCLRBIT_ATTRBIT(b, p)	((b)->bits[(p) / 32] &= ~(1 << ((p) % 32)))
 
 #define	NFSCLRALL_ATTRBIT(b, a)	do { 					\
 	(b)->bits[0] &= ~((a)->bits[0]);	 			\
 	(b)->bits[1] &= ~((a)->bits[1]);	 			\
 	(b)->bits[2] &= ~((a)->bits[2]);				\
 } while (0)
 
 #define	NFSCLRNOT_ATTRBIT(b, a)	do { 					\
 	(b)->bits[0] &= ((a)->bits[0]);		 			\
 	(b)->bits[1] &= ((a)->bits[1]);		 			\
 	(b)->bits[2] &= ((a)->bits[2]);		 			\
 } while (0)
 
 #define	NFSCLRNOTFILLABLE_ATTRBIT(b, n) do { 				\
 	(b)->bits[0] &= NFSATTRBIT_SUPP0;	 			\
 	(b)->bits[1] &= NFSATTRBIT_SUPP1;				\
 	(b)->bits[2] &= NFSATTRBIT_SUPP2;				\
 	if (((n)->nd_flag & ND_NFSV41) == 0) {				\
 		(b)->bits[1] &= ~NFSATTRBIT_NFSV41_1;			\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV41_2;			\
 	}								\
 	if (((n)->nd_flag & ND_NFSV42) == 0)				\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV42_2;			\
 } while (0)
 
 #define	NFSCLRNOTSETABLE_ATTRBIT(b, n) do { 				\
 	(b)->bits[0] &= NFSATTRBIT_SETABLE0;	 			\
 	(b)->bits[1] &= NFSATTRBIT_SETABLE1;				\
 	(b)->bits[2] &= NFSATTRBIT_SETABLE2;				\
 	if (((n)->nd_flag & ND_NFSV41) == 0)				\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV41_2;			\
 	if (((n)->nd_flag & ND_NFSV42) == 0)				\
 		(b)->bits[2] &= ~NFSATTRBIT_NFSV42_2;			\
 } while (0)
 
 #define	NFSNONZERO_ATTRBIT(b)	((b)->bits[0] || (b)->bits[1] || (b)->bits[2])
 #define	NFSEQUAL_ATTRBIT(b, p)	((b)->bits[0] == (p)->bits[0] &&	\
 	(b)->bits[1] == (p)->bits[1] && (b)->bits[2] == (p)->bits[2])
 
 #define	NFSGETATTR_ATTRBIT(b) do { 					\
 	(b)->bits[0] = NFSATTRBIT_GETATTR0;	 			\
 	(b)->bits[1] = NFSATTRBIT_GETATTR1;				\
 	(b)->bits[2] = NFSATTRBIT_GETATTR2;				\
 } while (0)
 
 #define	NFSWCCATTR_ATTRBIT(b) do { 					\
 	(b)->bits[0] = NFSATTRBIT_WCCATTR0;	 			\
 	(b)->bits[1] = NFSATTRBIT_WCCATTR1;				\
 	(b)->bits[2] = NFSATTRBIT_WCCATTR2;				\
 } while (0)
 
 #define	NFSWRITEGETATTR_ATTRBIT(b) do { 				\
 	(b)->bits[0] = NFSATTRBIT_WRITEGETATTR0;			\
 	(b)->bits[1] = NFSATTRBIT_WRITEGETATTR1;			\
 	(b)->bits[2] = NFSATTRBIT_WRITEGETATTR2;			\
 } while (0)
 
 #define	NFSCBGETATTR_ATTRBIT(b, c) do { 				\
 	(c)->bits[0] = ((b)->bits[0] & NFSATTRBIT_CBGETATTR0);		\
 	(c)->bits[1] = ((b)->bits[1] & NFSATTRBIT_CBGETATTR1);		\
 	(c)->bits[2] = ((b)->bits[2] & NFSATTRBIT_CBGETATTR2);		\
 } while (0)
 
 #define	NFSPATHCONF_GETATTRBIT(b) do { 					\
 	(b)->bits[0] = NFSGETATTRBIT_PATHCONF0;		 		\
 	(b)->bits[1] = NFSGETATTRBIT_PATHCONF1;				\
 	(b)->bits[2] = NFSGETATTRBIT_PATHCONF2;				\
 } while (0)
 
 #define	NFSSTATFS_GETATTRBIT(b)	do { 					\
 	(b)->bits[0] = NFSGETATTRBIT_STATFS0;	 			\
 	(b)->bits[1] = NFSGETATTRBIT_STATFS1;				\
 	(b)->bits[2] = NFSGETATTRBIT_STATFS2;				\
 } while (0)
 
 #define	NFSROOTFS_GETATTRBIT(b)	do { 					\
 	(b)->bits[0] = NFSGETATTRBIT_STATFS0 | NFSATTRBIT_GETATTR0 |	\
 	    NFSATTRBM_LEASETIME;					\
 	(b)->bits[1] = NFSGETATTRBIT_STATFS1 | NFSATTRBIT_GETATTR1;	\
 	(b)->bits[2] = NFSGETATTRBIT_STATFS2 | NFSATTRBIT_GETATTR2;	\
 } while (0)
 
 #define	NFSISSETSTATFS_ATTRBIT(b) 					\
 		(((b)->bits[0] & NFSATTRBIT_STATFS0) || 		\
 		 ((b)->bits[1] & NFSATTRBIT_STATFS1) ||			\
 		 ((b)->bits[2] & NFSATTRBIT_STATFS2))
 
 #define	NFSCLRSTATFS_ATTRBIT(b)	do { 					\
 	(b)->bits[0] &= ~NFSATTRBIT_STATFS0;	 			\
 	(b)->bits[1] &= ~NFSATTRBIT_STATFS1;				\
 	(b)->bits[2] &= ~NFSATTRBIT_STATFS2;				\
 } while (0)
 
 #define	NFSREADDIRPLUS_ATTRBIT(b) do { 					\
 	(b)->bits[0] = NFSATTRBIT_READDIRPLUS0;		 		\
 	(b)->bits[1] = NFSATTRBIT_READDIRPLUS1;				\
 	(b)->bits[2] = NFSATTRBIT_READDIRPLUS2;				\
 } while (0)
 
 #define	NFSREFERRAL_ATTRBIT(b) do { 					\
 	(b)->bits[0] = NFSATTRBIT_REFERRAL0;		 		\
 	(b)->bits[1] = NFSATTRBIT_REFERRAL1;				\
 	(b)->bits[2] = NFSATTRBIT_REFERRAL2;				\
 } while (0)
 
 /*
  * Here is the definition of the operation bits array and macros that
  * manipulate it.
  * THE MACROS MUST BE MANUALLY MODIFIED IF NFSOPBIT_MAXWORDS CHANGES!!
  * It is (NFSV42_NOPS + 31) / 32.
  */
 #define	NFSOPBIT_MAXWORDS	3
 
 typedef struct {
 	uint32_t bits[NFSOPBIT_MAXWORDS];
 } nfsopbit_t;
 
 #define	NFSZERO_OPBIT(b) do {						\
 	(b)->bits[0] = 0;						\
 	(b)->bits[1] = 0;						\
 	(b)->bits[2] = 0;						\
 } while (0)
 
 #define	NFSSET_OPBIT(t, f) do {						\
 	(t)->bits[0] = (f)->bits[0];			 		\
 	(t)->bits[1] = (f)->bits[1];					\
 	(t)->bits[2] = (f)->bits[2];					\
 } while (0)
 
 #define	NFSISSET_OPBIT(b, p)	((b)->bits[(p) / 32] & (1 << ((p) % 32)))
 #define	NFSSETBIT_OPBIT(b, p)	((b)->bits[(p) / 32] |= (1 << ((p) % 32)))
 #define	NFSCLRBIT_OPBIT(b, p)	((b)->bits[(p) / 32] &= ~(1 << ((p) % 32)))
 
 /*
  * Store uid, gid creds that were used when the stateid was acquired.
  * The RPC layer allows NFS_MAXGRPS + 1 groups to go out on the wire,
  * so that's how many gets stored here.
  */
 struct nfscred {
 	uid_t 		nfsc_uid;
 	gid_t		nfsc_groups[NFS_MAXGRPS + 1];
 	int		nfsc_ngroups;
 };
 
 /*
  * Constants that define the file handle for the V4 root directory.
  * (The FSID must never be used by other file systems that are exported.)
  */
 #define	NFSV4ROOT_FSID0		((int32_t) -1)
 #define	NFSV4ROOT_FSID1		((int32_t) -1)
 #define	NFSV4ROOT_REFERRAL	((int32_t) -2)
 #define	NFSV4ROOT_INO		2	/* It's traditional */
 #define	NFSV4ROOT_GEN		1
 
 /*
  * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
  * What should be in this set is open to debate, but I believe that since
  * I/O system calls on ufs are never interrupted by signals the set should
  * be minimal. My reasoning is that many current programs that use signals
  * such as SIGALRM will not expect file I/O system calls to be interrupted
  * by them and break.
  */
 #if defined(_KERNEL) || defined(KERNEL)
 
 struct uio; struct buf; struct vattr; struct nameidata;	/* XXX */
 
 /*
  * Socket errors ignored for connectionless sockets?
  * For now, ignore them all
  */
 #define	NFSIGNORE_SOERROR(s, e) 					\
 		((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
 		((s) & PR_CONNREQUIRED) == 0)
 
 /*
  * This structure holds socket information for a connection. Used by the
  * client and the server for callbacks.
  */
 struct nfssockreq {
 	NFSSOCKADDR_T	nr_nam;
 	int		nr_sotype;
 	int		nr_soproto;
 	int		nr_soflags;
 	struct ucred	*nr_cred;
 	int		nr_lock;
 	NFSMUTEX_T	nr_mtx;
 	u_int32_t	nr_prog;
 	u_int32_t	nr_vers;
 	struct __rpc_client *nr_client;
 	AUTH		*nr_auth;
+	char		nr_srvprinc[1];
 };
 
 /*
  * And associated nr_lock bits.
  */
 #define	NFSR_SNDLOCK		0x01
 #define	NFSR_WANTSND		0x02
 #define	NFSR_RCVLOCK		0x04
 #define	NFSR_WANTRCV		0x08
 #define	NFSR_RESERVEDPORT	0x10
 #define	NFSR_LOCALHOST		0x20
 
 /*
  * Queue head for nfsreq's
  */
 TAILQ_HEAD(nfsreqhead, nfsreq);
 
 /* This is the only nfsreq R_xxx flag still used. */
 #define	R_DONTRECOVER	0x00000100	/* don't initiate recovery when this
 					   rpc gets a stale state reply */
 
 /*
  * Network address hash list element
  */
 union nethostaddr {
 	struct in_addr	had_inet;
 	struct in6_addr had_inet6;
 };
 
 /*
  * Structure of list of mechanisms.
  */
 struct nfsgss_mechlist {
 	int	len;
 	const u_char	*str;
 	int	totlen;
 };
 #define	KERBV_MECH	0	/* position in list */
 
 /*
  * This structure is used by the server for describing each request.
  */
 struct nfsrv_descript {
 	struct mbuf		*nd_mrep;	/* Request mbuf list */
 	struct mbuf		*nd_md;		/* Current dissect mbuf */
 	struct mbuf		*nd_mreq;	/* Reply mbuf list */
 	struct mbuf		*nd_mb;		/* Current build mbuf */
 	NFSSOCKADDR_T		nd_nam;		/* and socket addr */
 	NFSSOCKADDR_T		nd_nam2;	/* return socket addr */
 	caddr_t			nd_dpos;	/* Current dissect pos */
 	caddr_t			nd_bpos;	/* Current build pos */
 	u_int64_t		nd_flag;	/* nd_flag */
 	u_int16_t		nd_procnum;	/* RPC # */
 	u_int32_t		nd_repstat;	/* Reply status */
 	int			*nd_errp;	/* Pointer to ret status */
 	u_int32_t		nd_retxid;	/* Reply xid */
 	struct nfsrvcache	*nd_rp;		/* Assoc. cache entry */
 	fhandle_t		nd_fh;		/* File handle */
 	struct ucred		*nd_cred;	/* Credentials */
 	uid_t			nd_saveduid;	/* Saved uid */
 	u_int64_t		nd_sockref;	/* Rcv socket ref# */
 	u_int64_t		nd_compref;	/* Compound RPC ref# */
 	time_t			nd_tcpconntime;	/* Time TCP connection est. */
 	nfsquad_t		nd_clientid;	/* Implied clientid */
 	int			nd_gssnamelen;	/* principal name length */
 	char			*nd_gssname;	/* principal name */
 	uint32_t		*nd_slotseq;	/* ptr to slot seq# in req */
 	uint8_t			nd_sessionid[NFSX_V4SESSIONID];	/* Session id */
 	uint32_t		nd_slotid;	/* Slotid for this RPC */
 	SVCXPRT			*nd_xprt;	/* Server RPC handle */
 	uint32_t		*nd_sequence;	/* Sequence Op. ptr */
 	nfsv4stateid_t		nd_curstateid;	/* Current StateID */
 	nfsv4stateid_t		nd_savedcurstateid; /* Saved Current StateID */
 	uint32_t		nd_maxreq;	/* Max. request (session). */
 	uint32_t		nd_maxresp;	/* Max. reply (session). */
 	int			nd_bextpg;	/* Current ext_pgs page */
 	int			nd_bextpgsiz;	/* Bytes left in page */
 	int			nd_maxextsiz;	/* Max ext_pgs mbuf size */
 	nfsopbit_t		nd_allowops;	/* Allowed ops ND_MACHCRED */
 };
 
 #define	nd_princlen	nd_gssnamelen
 #define	nd_principal	nd_gssname
 
 /* Bits for "nd_flag" */
 #define	ND_DONTSAVEREPLY 	0x00000001
 #define	ND_SAVEREPLY		0x00000002
 #define	ND_NFSV2		0x00000004
 #define	ND_NFSV3		0x00000008
 #define	ND_NFSV4		0x00000010
 #define	ND_KERBV		0x00000020
 #define	ND_GSSINTEGRITY		0x00000040
 #define	ND_GSSPRIVACY		0x00000080
 #define	ND_WINDOWVERF		0x00000100
 #define	ND_GSSINITREPLY		0x00000200
 #define	ND_STREAMSOCK		0x00000400
 #define	ND_PUBLOOKUP		0x00000800
 #define	ND_USEGSSNAME		0x00001000
 #define	ND_SAMETCPCONN		0x00002000
 #define	ND_IMPLIEDCLID		0x00004000
 #define	ND_NOMOREDATA		0x00008000
 #define	ND_V4WCCATTR		0x00010000
 #define	ND_NFSCB		0x00020000
 #define	ND_AUTHNONE		0x00040000
 #define	ND_EXAUTHSYS		0x00080000
 #define	ND_EXGSS		0x00100000
 #define	ND_EXGSSINTEGRITY	0x00200000
 #define	ND_EXGSSPRIVACY		0x00400000
 #define	ND_INCRSEQID		0x00800000
 #define	ND_NFSCL		0x01000000
 #define	ND_NFSV41		0x02000000
 #define	ND_HASSEQUENCE		0x04000000
 #define	ND_CACHETHIS		0x08000000
 #define	ND_LASTOP		0x10000000
 #define	ND_LOOPBADSESS		0x20000000
 #define	ND_DSSERVER		0x40000000
 #define	ND_CURSTATEID		0x80000000
 #define	ND_SAVEDCURSTATEID	0x100000000
 #define	ND_HASSLOTID		0x200000000
 #define	ND_NFSV42		0x400000000
 #define	ND_EXTPG		0x800000000
 #define	ND_TLS			0x1000000000
 #define	ND_TLSCERT		0x2000000000
 #define	ND_TLSCERTUSER		0x4000000000
 #define	ND_EXTLS		0x8000000000
 #define	ND_EXTLSCERT		0x10000000000
 #define	ND_EXTLSCERTUSER	0x20000000000
 #define	ND_ERELOOKUP		0x40000000000
 #define	ND_MACHCRED		0x80000000000
 
 /*
  * ND_GSS should be the "or" of all GSS type authentications.
  */
 #define	ND_GSS		(ND_KERBV)
 
 struct nfsv4_opflag {
 	int	retfh;
 	int	needscfh;
 	int	savereply;
 	int	modifyfs;
 	int	lktype;
 	int	needsseq;
 	int	loopbadsess;
 };
 
 /*
  * Flags used to indicate what to do w.r.t. seqid checking.
  */
 #define	NFSRVSEQID_FIRST	0x01
 #define	NFSRVSEQID_LAST		0x02
 #define	NFSRVSEQID_OPEN		0x04
 
 /*
  * assign a doubly linked list to a new head
  * and prepend one list into another.
  */
 #define	LIST_NEWHEAD(nhead, ohead, field) do { 				\
 	if (((nhead)->lh_first = (ohead)->lh_first) != NULL) 		\
 		(ohead)->lh_first->field.le_prev = &(nhead)->lh_first; 	\
 	(ohead)->lh_first = NULL; 					\
     } while (0)
 
 #define	LIST_PREPEND(head, phead, lelm, field) do {			\
 	if ((head)->lh_first != NULL) {					\
 		(lelm)->field.le_next = (head)->lh_first;		\
 		(lelm)->field.le_next->field.le_prev =			\
 		    &(lelm)->field.le_next;				\
 	}								\
 	(head)->lh_first = (phead)->lh_first;				\
 	(head)->lh_first->field.le_prev = &(head)->lh_first;		\
     } while (0)
 
 /*
  * File handle structure for client. Malloc'd to the correct length with
  * malloc type M_NFSFH.
  */
 struct nfsfh {
 	u_int16_t	nfh_len;	/* Length of file handle */
 	u_int8_t	nfh_fh[1];	/* and the file handle */
 };
 
 /*
  * File handle structure for server. The NFSRV_MAXFH constant is
  * set in nfsdport.h. I use a 32bit length, so that alignment is
  * preserved.
  */
 struct nfsrvfh {
 	u_int32_t	nfsrvfh_len;
 	u_int8_t	nfsrvfh_data[NFSRV_MAXFH];
 };
 
 /*
  * This structure is used for sleep locks on the NFSv4 nfsd threads and
  * NFSv4 client data structures.
  */
 struct nfsv4lock {
 	u_int32_t	nfslock_usecnt;
 	u_int8_t	nfslock_lock;
 };
 #define	NFSV4LOCK_LOCK		0x01
 #define	NFSV4LOCK_LOCKWANTED	0x02
 #define	NFSV4LOCK_WANTED	0x04
 
 /*
  * Values for the override argument for nfsvno_accchk().
  */
 #define	NFSACCCHK_NOOVERRIDE		0
 #define	NFSACCCHK_ALLOWROOT		1
 #define	NFSACCCHK_ALLOWOWNER		2
 
 /*
  * and values for the vpislocked argument for nfsvno_accchk().
  */
 #define	NFSACCCHK_VPNOTLOCKED		0
 #define	NFSACCCHK_VPISLOCKED		1
 
 /*
  * Slot for the NFSv4.1 Sequence Op.
  */
 struct nfsslot {
 	int		nfssl_inprog;
 	uint32_t	nfssl_seq;
 	struct mbuf	*nfssl_reply;
 };
 
 /* Enumerated type for nfsuserd state. */
 typedef enum { NOTRUNNING=0, STARTSTOP=1, RUNNING=2 } nfsuserd_state;
 
 #endif	/* _KERNEL */
 
 #endif	/* _NFS_NFS_H */
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index 29fbb8dc4351..7ca150d4f54c 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -1,1673 +1,1680 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1989, 1991, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  */
 
 #include <sys/cdefs.h>
 /*
  * Socket operations for use by nfs
  */
 
 #include "opt_kgssapi.h"
 #include "opt_nfs.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/signalvar.h>
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/vnode.h>
 
 #include <rpc/rpc.h>
 #include <rpc/krpc.h>
 
 #include <kgssapi/krb5/kcrypto.h>
 
 #include <fs/nfs/nfsport.h>
 
 #ifdef KDTRACE_HOOKS
 #include <sys/dtrace_bsd.h>
 
 dtrace_nfsclient_nfs23_start_probe_func_t
 		dtrace_nfscl_nfs234_start_probe;
 
 dtrace_nfsclient_nfs23_done_probe_func_t
 		dtrace_nfscl_nfs234_done_probe;
 
 /*
  * Registered probes by RPC type.
  */
 uint32_t	nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
 uint32_t	nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
 
 uint32_t	nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
 uint32_t	nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
 
 uint32_t	nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
 uint32_t	nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
 #endif
 
 NFSSTATESPINLOCK;
 NFSREQSPINLOCK;
 NFSDLOCKMUTEX;
 NFSCLSTATEMUTEX;
 extern struct nfsstatsv1 nfsstatsv1;
 extern struct nfsreqhead nfsd_reqq;
 extern int nfscl_ticks;
 extern void (*ncl_call_invalcaches)(struct vnode *);
 extern int nfs_numnfscbd;
 extern int nfscl_debuglevel;
 extern int nfsrv_lease;
 
 SVCPOOL		*nfscbd_pool;
 int		nfs_bufpackets = 4;
 static int	nfsrv_gsscallbackson = 0;
 static int	nfs_reconnects;
 static int	nfs3_jukebox_delay = 10;
 static int	nfs_skip_wcc_data_onerr = 1;
 static int	nfs_dsretries = 2;
 static struct timespec	nfs_trylater_max = {
 	.tv_sec		= NFS_TRYLATERDEL,
 	.tv_nsec	= 0,
 };
 
 SYSCTL_DECL(_vfs_nfs);
 
 SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0,
     "Buffer reservation size 2 < x < 64");
 SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
     "Number of times the nfs client has had to reconnect");
 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW, &nfs3_jukebox_delay, 0,
     "Number of seconds to delay a retry after receiving EJUKEBOX");
 SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_data_onerr, 0,
     "Disable weak cache consistency checking when server returns an error");
 SYSCTL_INT(_vfs_nfs, OID_AUTO, dsretries, CTLFLAG_RW, &nfs_dsretries, 0,
     "Number of retries for a DS RPC before failure");
 
 static void	nfs_down(struct nfsmount *, struct thread *, const char *,
     int, int);
 static void	nfs_up(struct nfsmount *, struct thread *, const char *,
     int, int);
 static int	nfs_msg(struct thread *, const char *, const char *, int);
 
 struct nfs_cached_auth {
 	int		ca_refs; /* refcount, including 1 from the cache */
 	uid_t		ca_uid;	 /* uid that corresponds to this auth */
 	AUTH		*ca_auth; /* RPC auth handle */
 };
 
 static int nfsv2_procid[NFS_V3NPROCS] = {
 	NFSV2PROC_NULL,
 	NFSV2PROC_GETATTR,
 	NFSV2PROC_SETATTR,
 	NFSV2PROC_LOOKUP,
 	NFSV2PROC_NOOP,
 	NFSV2PROC_READLINK,
 	NFSV2PROC_READ,
 	NFSV2PROC_WRITE,
 	NFSV2PROC_CREATE,
 	NFSV2PROC_MKDIR,
 	NFSV2PROC_SYMLINK,
 	NFSV2PROC_CREATE,
 	NFSV2PROC_REMOVE,
 	NFSV2PROC_RMDIR,
 	NFSV2PROC_RENAME,
 	NFSV2PROC_LINK,
 	NFSV2PROC_READDIR,
 	NFSV2PROC_NOOP,
 	NFSV2PROC_STATFS,
 	NFSV2PROC_NOOP,
 	NFSV2PROC_NOOP,
 	NFSV2PROC_NOOP,
 };
 
 /*
  * This static array indicates that a NFSv4 RPC should use
  * RPCSEC_GSS, if the mount indicates that via sec=krb5[ip].
  * System RPCs that do not use file handles will be false
  * in this array so that they will use AUTH_SYS when the
  * "syskrb5" mount option is specified, along with
  * "sec=krb5[ip]".
  */
 static bool nfscl_use_gss[NFSV42_NPROCS] = {
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	false,		/* SetClientID */
 	false,		/* SetClientIDConfirm */
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	false,		/* Renew */
 	true,
 	false,		/* ReleaseLockOwn */
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	false,		/* ExchangeID */
 	false,		/* CreateSession */
 	false,		/* DestroySession */
 	false,		/* DestroyClientID */
 	false,		/* FreeStateID */
 	true,
 	true,
 	true,
 	true,
 	false,		/* ReclaimComplete */
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	true,
 	false,		/* BindConnectionToSession */
 	true,
 	true,
 	true,
 	true,
 };
 
 /*
  * Initialize sockets and congestion for a new NFS connection.
  * We do not free the sockaddr if error.
  * Which arguments are set to NULL indicate what kind of call it is.
  * cred == NULL --> a call to connect to a pNFS DS
  * nmp == NULL --> indicates an upcall to userland or a NFSv4.0 callback
  */
 int
 newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
     struct ucred *cred, NFSPROC_T *p, int callback_retry_mult, bool dotls,
     struct __rpc_client **clipp)
 {
 	int rcvreserve, sndreserve;
 	int pktscale, pktscalesav;
 	struct sockaddr *saddr;
 	struct ucred *origcred;
 	CLIENT *client;
 	struct netconfig *nconf;
 	struct socket *so;
 	int one = 1, retries, error = 0;
 	struct thread *td = curthread;
 	SVCXPRT *xprt;
 	struct timeval timo;
 	uint64_t tval;
 
 	/*
 	 * We need to establish the socket using the credentials of
 	 * the mountpoint.  Some parts of this process (such as
 	 * sobind() and soconnect()) will use the curent thread's
 	 * credential instead of the socket credential.  To work
 	 * around this, temporarily change the current thread's
 	 * credential to that of the mountpoint.
 	 *
 	 * XXX: It would be better to explicitly pass the correct
 	 * credential to sobind() and soconnect().
 	 */
 	origcred = td->td_ucred;
 
 	/*
 	 * Use the credential in nr_cred, if not NULL.
 	 */
 	if (nrp->nr_cred != NULL)
 		td->td_ucred = nrp->nr_cred;
 	else
 		td->td_ucred = cred;
 	saddr = nrp->nr_nam;
 
 	if (saddr->sa_family == AF_INET)
 		if (nrp->nr_sotype == SOCK_DGRAM)
 			nconf = getnetconfigent("udp");
 		else
 			nconf = getnetconfigent("tcp");
 	else
 		if (nrp->nr_sotype == SOCK_DGRAM)
 			nconf = getnetconfigent("udp6");
 		else
 			nconf = getnetconfigent("tcp6");
 			
 	pktscale = nfs_bufpackets;
 	if (pktscale < 2)
 		pktscale = 2;
 	if (pktscale > 64)
 		pktscale = 64;
 	pktscalesav = pktscale;
 	/*
 	 * soreserve() can fail if sb_max is too small, so shrink pktscale
 	 * and try again if there is an error.
 	 * Print a log message suggesting increasing sb_max.
 	 * Creating a socket and doing this is necessary since, if the
 	 * reservation sizes are too large and will make soreserve() fail,
 	 * the connection will work until a large send is attempted and
 	 * then it will loop in the krpc code.
 	 */
 	so = NULL;
 	saddr = NFSSOCKADDR(nrp->nr_nam, struct sockaddr *);
 	error = socreate(saddr->sa_family, &so, nrp->nr_sotype, 
 	    nrp->nr_soproto, td->td_ucred, td);
 	if (error != 0)
 		goto out;
 	do {
 	    if (error != 0 && pktscale > 2) {
 		if (nmp != NULL && nrp->nr_sotype == SOCK_STREAM &&
 		    pktscale == pktscalesav) {
 		    /*
 		     * Suggest vfs.nfs.bufpackets * maximum RPC message,
 		     * adjusted for the sb_max->sb_max_adj conversion of
 		     * MCLBYTES / (MSIZE + MCLBYTES) as the minimum setting
 		     * for kern.ipc.maxsockbuf.
 		     */
 		    tval = (NFS_MAXBSIZE + NFS_MAXXDR) * nfs_bufpackets;
 		    tval *= MSIZE + MCLBYTES;
 		    tval += MCLBYTES - 1; /* Round up divide by MCLBYTES. */
 		    tval /= MCLBYTES;
 		    printf("Consider increasing kern.ipc.maxsockbuf to a "
 			"minimum of %ju to support %ubyte NFS I/O\n",
 			(uintmax_t)tval, NFS_MAXBSIZE);
 		}
 		pktscale--;
 	    }
 	    if (nrp->nr_sotype == SOCK_DGRAM) {
 		if (nmp != NULL) {
 			sndreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) *
 			    pktscale;
 			rcvreserve = (NFS_MAXDGRAMDATA + NFS_MAXPKTHDR) *
 			    pktscale;
 		} else {
 			sndreserve = rcvreserve = 1024 * pktscale;
 		}
 	    } else {
 		if (nrp->nr_sotype != SOCK_STREAM)
 			panic("nfscon sotype");
 		if (nmp != NULL) {
 			sndreserve = (NFS_MAXBSIZE + NFS_MAXXDR) *
 			    pktscale;
 			rcvreserve = (NFS_MAXBSIZE + NFS_MAXXDR) *
 			    pktscale;
 		} else {
 			sndreserve = rcvreserve = 1024 * pktscale;
 		}
 	    }
 	    error = soreserve(so, sndreserve, rcvreserve);
 	    if (error != 0 && nmp != NULL && nrp->nr_sotype == SOCK_STREAM &&
 		pktscale <= 2)
 		printf("Must increase kern.ipc.maxsockbuf or reduce"
 		    " rsize, wsize\n");
 	} while (error != 0 && pktscale > 2);
 	soclose(so);
 	if (error != 0)
 		goto out;
 
 	client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog,
 	    nrp->nr_vers, sndreserve, rcvreserve);
 	CLNT_CONTROL(client, CLSET_WAITCHAN, "nfsreq");
 	if (nmp != NULL) {
 		if ((nmp->nm_flag & NFSMNT_INT))
 			CLNT_CONTROL(client, CLSET_INTERRUPTIBLE, &one);
 		if ((nmp->nm_flag & NFSMNT_RESVPORT))
 			CLNT_CONTROL(client, CLSET_PRIVPORT, &one);
 		if (NFSHASTLS(nmp)) {
 			CLNT_CONTROL(client, CLSET_TLS, &one);
 			if (nmp->nm_tlscertname != NULL)
 				CLNT_CONTROL(client, CLSET_TLSCERTNAME,
 				    nmp->nm_tlscertname);
 		}
 		if (NFSHASSOFT(nmp)) {
 			if (nmp->nm_sotype == SOCK_DGRAM)
 				/*
 				 * For UDP, the large timeout for a reconnect
 				 * will be set to "nm_retry * nm_timeo / 2", so
 				 * we only want to do 2 reconnect timeout
 				 * retries.
 				 */
 				retries = 2;
 			else
 				retries = nmp->nm_retry;
 		} else
 			retries = INT_MAX;
 		if (NFSHASNFSV4N(nmp)) {
 			if (cred != NULL) {
 				if (NFSHASSOFT(nmp)) {
 					/*
 					 * This should be a DS mount.
 					 * Use CLSET_TIMEOUT to set the timeout
 					 * for connections to DSs instead of
 					 * specifying a timeout on each RPC.
 					 * This is done so that SO_SNDTIMEO
 					 * is set on the TCP socket as well
 					 * as specifying a time limit when
 					 * waiting for an RPC reply.  Useful
 					 * if the send queue for the TCP
 					 * connection has become constipated,
 					 * due to a failed DS.
 					 * The choice of lease_duration / 4 is
 					 * fairly arbitrary, but seems to work
 					 * ok, with a lower bound of 10sec.
 					 */
 					timo.tv_sec = nfsrv_lease / 4;
 					if (timo.tv_sec < 10)
 						timo.tv_sec = 10;
 					timo.tv_usec = 0;
 					CLNT_CONTROL(client, CLSET_TIMEOUT,
 					    &timo);
 				}
 				/*
 				 * Make sure the nfscbd_pool doesn't get
 				 * destroyed while doing this.
 				 */
 				NFSD_LOCK();
 				if (nfs_numnfscbd > 0) {
 					nfs_numnfscbd++;
 					NFSD_UNLOCK();
 					xprt = svc_vc_create_backchannel(
 					    nfscbd_pool);
 					CLNT_CONTROL(client, CLSET_BACKCHANNEL,
 					    xprt);
 					NFSD_LOCK();
 					nfs_numnfscbd--;
 					if (nfs_numnfscbd == 0)
 						wakeup(&nfs_numnfscbd);
 				}
 				NFSD_UNLOCK();
 			} else {
 				/*
 				 * cred == NULL for a DS connect.
 				 * For connects to a DS, set a retry limit
 				 * so that failed DSs will be detected.
 				 * This is ok for NFSv4.1, since a DS does
 				 * not maintain open/lock state and is the
 				 * only case where using a "soft" mount is
 				 * recommended for NFSv4.
 				 * For mounts from the MDS to DS, this is done
 				 * via mount options, but that is not the case
 				 * here.  The retry limit here can be adjusted
 				 * via the sysctl vfs.nfs.dsretries.
 				 * See the comment above w.r.t. timeout.
 				 */
 				timo.tv_sec = nfsrv_lease / 4;
 				if (timo.tv_sec < 10)
 					timo.tv_sec = 10;
 				timo.tv_usec = 0;
 				CLNT_CONTROL(client, CLSET_TIMEOUT, &timo);
 				retries = nfs_dsretries;
 			}
 		}
 	} else {
 		/*
 		 * Three cases:
 		 * - Null RPC callback to client
 		 * - Non-Null RPC callback to client, wait a little longer
 		 * - upcalls to nfsuserd and gssd (clp == NULL)
 		 */
 		if (callback_retry_mult == 0) {
 			retries = NFSV4_UPCALLRETRY;
 			CLNT_CONTROL(client, CLSET_PRIVPORT, &one);
 		} else {
 			retries = NFSV4_CALLBACKRETRY * callback_retry_mult;
 		}
 		if (dotls)
 			CLNT_CONTROL(client, CLSET_TLS, &one);
 	}
 	CLNT_CONTROL(client, CLSET_RETRIES, &retries);
 
 	if (nmp != NULL) {
 		/*
 		 * For UDP, there are 2 timeouts:
 		 * - CLSET_RETRY_TIMEOUT sets the initial timeout for the timer
 		 *   that does a retransmit of an RPC request using the same 
 		 *   socket and xid. This is what you normally want to do,
 		 *   since NFS servers depend on "same xid" for their
 		 *   Duplicate Request Cache.
 		 * - timeout specified in CLNT_CALL_MBUF(), which specifies when
 		 *   retransmits on the same socket should fail and a fresh
 		 *   socket created. Each of these timeouts counts as one
 		 *   CLSET_RETRIES as set above.
 		 * Set the initial retransmit timeout for UDP. This timeout
 		 * doesn't exist for TCP and the following call just fails,
 		 * which is ok.
 		 */
 		timo.tv_sec = nmp->nm_timeo / NFS_HZ;
 		timo.tv_usec = (nmp->nm_timeo % NFS_HZ) * 1000000 / NFS_HZ;
 		CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, &timo);
 	}
 
 	/*
 	 * *clipp is &nrp->nr_client or &nm_aconn[nmp->nm_nextaconn].
 	 * The latter case is for additional connections specified by the
 	 * "nconnect" mount option.  nr_mtx etc is used for these additional
 	 * connections, as well as nr_client in the nfssockreq
 	 * structure for the mount.
 	 */
 	mtx_lock(&nrp->nr_mtx);
 	if (*clipp != NULL) {
 		mtx_unlock(&nrp->nr_mtx);
 		/*
 		 * Someone else already connected.
 		 */
 		CLNT_RELEASE(client);
 	} else {
 		*clipp = client;
 		/*
 		 * Protocols that do not require connections may be optionally
 		 * left unconnected for servers that reply from a port other
 		 * than NFS_PORT.
 		 */
 		if (nmp == NULL || (nmp->nm_flag & NFSMNT_NOCONN) == 0) {
 			mtx_unlock(&nrp->nr_mtx);
 			CLNT_CONTROL(client, CLSET_CONNECT, &one);
 		} else
 			mtx_unlock(&nrp->nr_mtx);
 	}
 
 out:
 	/* Restore current thread's credentials. */
 	td->td_ucred = origcred;
 
 	NFSEXITCODE(error);
 	return (error);
 }
 
 /*
  * NFS disconnect. Clean up and unlink.
  */
 void
 newnfs_disconnect(struct nfsmount *nmp, struct nfssockreq *nrp)
 {
 	CLIENT *client, *aconn[NFS_MAXNCONN - 1];
 	int i;
 
 	mtx_lock(&nrp->nr_mtx);
 	if (nrp->nr_client != NULL) {
 		client = nrp->nr_client;
 		nrp->nr_client = NULL;
 		if (nmp != NULL && nmp->nm_aconnect > 0) {
 			for (i = 0; i < nmp->nm_aconnect; i++) {
 				aconn[i] = nmp->nm_aconn[i];
 				nmp->nm_aconn[i] = NULL;
 			}
 		}
 		mtx_unlock(&nrp->nr_mtx);
 		rpc_gss_secpurge_call(client);
 		CLNT_CLOSE(client);
 		CLNT_RELEASE(client);
 		if (nmp != NULL && nmp->nm_aconnect > 0) {
 			for (i = 0; i < nmp->nm_aconnect; i++) {
 				if (aconn[i] != NULL) {
 					rpc_gss_secpurge_call(aconn[i]);
 					CLNT_CLOSE(aconn[i]);
 					CLNT_RELEASE(aconn[i]);
 				}
 			}
 		}
 	} else {
 		mtx_unlock(&nrp->nr_mtx);
 	}
 }
 
 static AUTH *
 nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
     char *srv_principal, gss_OID mech_oid, struct ucred *cred)
 {
 	rpc_gss_service_t svc;
 	AUTH *auth;
 
 	switch (secflavour) {
 	case RPCSEC_GSS_KRB5:
 	case RPCSEC_GSS_KRB5I:
 	case RPCSEC_GSS_KRB5P:
 		if (!mech_oid) {
 			if (!rpc_gss_mech_to_oid_call("kerberosv5", &mech_oid))
 				return (NULL);
 		}
 		if (secflavour == RPCSEC_GSS_KRB5)
 			svc = rpc_gss_svc_none;
 		else if (secflavour == RPCSEC_GSS_KRB5I)
 			svc = rpc_gss_svc_integrity;
 		else
 			svc = rpc_gss_svc_privacy;
 
-		if (clnt_principal == NULL)
+		if (clnt_principal == NULL) {
+			NFSCL_DEBUG(1, "nfs_getauth: clnt princ=NULL, "
+			    "srv princ=%s\n", srv_principal);
 			auth = rpc_gss_secfind_call(nrp->nr_client, cred,
 			    srv_principal, mech_oid, svc);
-		else {
+		} else {
+			NFSCL_DEBUG(1, "nfs_getauth: clnt princ=%s "
+			    "srv princ=%s\n", clnt_principal, srv_principal);
 			auth = rpc_gss_seccreate_call(nrp->nr_client, cred,
 			    clnt_principal, srv_principal, "kerberosv5",
 			    svc, NULL, NULL, NULL);
 			return (auth);
 		}
 		if (auth != NULL)
 			return (auth);
 		/* fallthrough */
 	case AUTH_SYS:
 	default:
 		return (authunix_create(cred));
 	}
 }
 
 /*
  * Callback from the RPC code to generate up/down notifications.
  */
 
 struct nfs_feedback_arg {
 	struct nfsmount *nf_mount;
 	int		nf_lastmsg;	/* last tprintf */
 	int		nf_tprintfmsg;
 	struct thread	*nf_td;
 };
 
 static void
 nfs_feedback(int type, int proc, void *arg)
 {
 	struct nfs_feedback_arg *nf = (struct nfs_feedback_arg *) arg;
 	struct nfsmount *nmp = nf->nf_mount;
 	time_t now;
 
 	switch (type) {
 	case FEEDBACK_REXMIT2:
 	case FEEDBACK_RECONNECT:
 		now = NFSD_MONOSEC;
 		if (nf->nf_lastmsg + nmp->nm_tprintf_delay < now) {
 			nfs_down(nmp, nf->nf_td,
 			    "not responding", 0, NFSSTA_TIMEO);
 			nf->nf_tprintfmsg = TRUE;
 			nf->nf_lastmsg = now;
 		}
 		break;
 
 	case FEEDBACK_OK:
 		nfs_up(nf->nf_mount, nf->nf_td,
 		    "is alive again", NFSSTA_TIMEO, nf->nf_tprintfmsg);
 		break;
 	}
 }
 
 /*
  * newnfs_request - goes something like this
  *	- does the rpc by calling the krpc layer
  *	- break down rpc header and return with nfs reply
  * nb: always frees up nd_mreq mbuf list
  */
 int
 newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
     struct nfsclient *clp, struct nfssockreq *nrp, vnode_t vp,
     struct thread *td, struct ucred *cred, u_int32_t prog, u_int32_t vers,
     u_char *retsum, int toplevel, u_int64_t *xidp, struct nfsclsession *dssep)
 {
 	uint32_t retseq, retval, slotseq, *tl;
 	int i = 0, j = 0, opcnt, set_sigset = 0, slot;
 	int error = 0, usegssname = 0, secflavour = AUTH_SYS;
 	int freeslot, maxslot, reterr, slotpos, timeo;
 	u_int16_t procnum;
 	u_int nextconn;
 	struct nfs_feedback_arg nf;
 	struct timeval timo;
 	AUTH *auth;
 	struct rpc_callextra ext;
 	enum clnt_stat stat;
 	struct nfsreq *rep = NULL;
 	char *srv_principal = NULL, *clnt_principal = NULL;
 	sigset_t oldset;
 	struct ucred *authcred;
 	struct nfsclsession *sep;
 	uint8_t sessionid[NFSX_V4SESSIONID];
 	bool nextconn_set;
 	struct timespec trylater_delay, ts, waituntil;
 
 	/* Initially 1msec. */
 	trylater_delay.tv_sec = 0;
 	trylater_delay.tv_nsec = 1000000;
 	sep = dssep;
 	if (xidp != NULL)
 		*xidp = 0;
 	/* Reject requests while attempting a forced unmount. */
 	if (nmp != NULL && NFSCL_FORCEDISM(nmp->nm_mountp)) {
 		m_freem(nd->nd_mreq);
 		return (ESTALE);
 	}
 
 	/*
 	 * Set authcred, which is used to acquire RPC credentials to
 	 * the cred argument, by default. The crhold() should not be
 	 * necessary, but will ensure that some future code change
 	 * doesn't result in the credential being free'd prematurely.
 	 */
 	authcred = crhold(cred);
 
 	/* For client side interruptible mounts, mask off the signals. */
 	if (nmp != NULL && td != NULL && NFSHASINT(nmp)) {
 		newnfs_set_sigmask(td, &oldset);
 		set_sigset = 1;
 	}
 
 	/*
 	 * If not already connected call newnfs_connect now.
 	 */
 	if (nrp->nr_client == NULL)
 		newnfs_connect(nmp, nrp, cred, td, 0, false, &nrp->nr_client);
 
 	/*
 	 * If the "nconnect" mount option was specified and this RPC is
 	 * one that can have a large RPC message and is being done through
 	 * the NFS/MDS server, use an additional connection. (When the RPC is
 	 * being done through the server/MDS, nrp == &nmp->nm_sockreq.)
 	 * The "nconnect" mount option normally has minimal effect when the
 	 * "pnfs" mount option is specified, since only Readdir RPCs are
 	 * normally done through the NFS/MDS server.
 	 */
 	nextconn_set = false;
 	if (nmp != NULL && nmp->nm_aconnect > 0 && nrp == &nmp->nm_sockreq &&
 	    (nd->nd_procnum == NFSPROC_READ ||
 	     nd->nd_procnum == NFSPROC_READDIR ||
 	     nd->nd_procnum == NFSPROC_READDIRPLUS ||
 	     nd->nd_procnum == NFSPROC_WRITE)) {
 		nextconn = atomic_fetchadd_int(&nmp->nm_nextaconn, 1);
 		nextconn %= nmp->nm_aconnect;
 		nextconn_set = true;
 		if (nmp->nm_aconn[nextconn] == NULL)
 			newnfs_connect(nmp, nrp, cred, td, 0, false,
 			    &nmp->nm_aconn[nextconn]);
 	}
 
 	/*
 	 * For a client side mount, nmp is != NULL and clp == NULL. For
 	 * server calls (callbacks or upcalls), nmp == NULL.
 	 */
 	if (clp != NULL) {
 		NFSLOCKSTATE();
 		if ((clp->lc_flags & LCL_GSS) && nfsrv_gsscallbackson) {
 			secflavour = RPCSEC_GSS_KRB5;
 			if (nd->nd_procnum != NFSPROC_NULL) {
 				if (clp->lc_flags & LCL_GSSINTEGRITY)
 					secflavour = RPCSEC_GSS_KRB5I;
 				else if (clp->lc_flags & LCL_GSSPRIVACY)
 					secflavour = RPCSEC_GSS_KRB5P;
 			}
 		}
 		NFSUNLOCKSTATE();
 	} else if (nmp != NULL && NFSHASKERB(nmp) &&
 	     nd->nd_procnum != NFSPROC_NULL && (!NFSHASSYSKRB5(nmp) ||
 	     nfscl_use_gss[nd->nd_procnum])) {
 		if (NFSHASALLGSSNAME(nmp) && nmp->nm_krbnamelen > 0)
 			nd->nd_flag |= ND_USEGSSNAME;
 		if ((nd->nd_flag & ND_USEGSSNAME) != 0) {
 			/*
 			 * If there is a client side host based credential,
 			 * use that, otherwise use the system uid, if set.
 			 * The system uid is in the nmp->nm_sockreq.nr_cred
 			 * credentials.
 			 */
 			if (nmp->nm_krbnamelen > 0) {
 				usegssname = 1;
 				clnt_principal = nmp->nm_krbname;
 			} else if (nmp->nm_uid != (uid_t)-1) {
 				KASSERT(nmp->nm_sockreq.nr_cred != NULL,
 				    ("newnfs_request: NULL nr_cred"));
 				crfree(authcred);
 				authcred = crhold(nmp->nm_sockreq.nr_cred);
 			}
 		} else if (nmp->nm_krbnamelen == 0 &&
 		    nmp->nm_uid != (uid_t)-1 && cred->cr_uid == (uid_t)0) {
 			/*
 			 * If there is no host based principal name and
 			 * the system uid is set and this is root, use the
 			 * system uid, since root won't have user
 			 * credentials in a credentials cache file.
 			 * The system uid is in the nmp->nm_sockreq.nr_cred
 			 * credentials.
 			 */
 			KASSERT(nmp->nm_sockreq.nr_cred != NULL,
 			    ("newnfs_request: NULL nr_cred"));
 			crfree(authcred);
 			authcred = crhold(nmp->nm_sockreq.nr_cred);
 		}
 		if (NFSHASINTEGRITY(nmp))
 			secflavour = RPCSEC_GSS_KRB5I;
 		else if (NFSHASPRIVACY(nmp))
 			secflavour = RPCSEC_GSS_KRB5P;
 		else
 			secflavour = RPCSEC_GSS_KRB5;
-		srv_principal = NFSMNT_SRVKRBNAME(nmp);
+		if (nrp->nr_srvprinc[0] == '\0')
+			srv_principal = NFSMNT_SRVKRBNAME(nmp);
+		else
+			srv_principal = nrp->nr_srvprinc;
 	} else if (nmp != NULL && (!NFSHASKERB(nmp) || NFSHASSYSKRB5(nmp)) &&
 	    nd->nd_procnum != NFSPROC_NULL &&
 	    (nd->nd_flag & ND_USEGSSNAME) != 0) {
 		/*
 		 * Use the uid that did the mount when the RPC is doing
 		 * NFSv4 system operations, as indicated by the
 		 * ND_USEGSSNAME flag, for the AUTH_SYS case.
 		 * The credentials in nm_sockreq.nr_cred were used for the
 		 * mount.
 		 */
 		KASSERT(nmp->nm_sockreq.nr_cred != NULL,
 		    ("newnfs_request: NULL nr_cred"));
 		crfree(authcred);
 		authcred = crhold(nmp->nm_sockreq.nr_cred);
 	}
 
 	if (nmp != NULL) {
 		bzero(&nf, sizeof(struct nfs_feedback_arg));
 		nf.nf_mount = nmp;
 		nf.nf_td = td;
 		nf.nf_lastmsg = NFSD_MONOSEC -
 		    ((nmp->nm_tprintf_delay)-(nmp->nm_tprintf_initial_delay));
 	}
 
 	if (nd->nd_procnum == NFSPROC_NULL)
 		auth = authnone_create();
 	else if (usegssname) {
 		/*
 		 * For this case, the authenticator is held in the
 		 * nfssockreq structure, so don't release the reference count
 		 * held on it. --> Don't AUTH_DESTROY() it in this function.
 		 */
 		if (nrp->nr_auth == NULL)
 			nrp->nr_auth = nfs_getauth(nrp, secflavour,
 			    clnt_principal, srv_principal, NULL, authcred);
 		else
 			rpc_gss_refresh_auth_call(nrp->nr_auth);
 		auth = nrp->nr_auth;
 	} else
 		auth = nfs_getauth(nrp, secflavour, NULL,
 		    srv_principal, NULL, authcred);
 	crfree(authcred);
 	if (auth == NULL) {
 		m_freem(nd->nd_mreq);
 		if (set_sigset)
 			newnfs_restore_sigmask(td, &oldset);
 		return (EACCES);
 	}
 	bzero(&ext, sizeof(ext));
 	ext.rc_auth = auth;
 	if (nmp != NULL) {
 		ext.rc_feedback = nfs_feedback;
 		ext.rc_feedback_arg = &nf;
 	}
 
 	procnum = nd->nd_procnum;
 	if ((nd->nd_flag & ND_NFSV4) &&
 	    nd->nd_procnum != NFSPROC_NULL &&
 	    nd->nd_procnum != NFSV4PROC_CBCOMPOUND)
 		procnum = NFSV4PROC_COMPOUND;
 
 	if (nmp != NULL) {
 		NFSINCRGLOBAL(nfsstatsv1.rpcrequests);
 
 		/* Map the procnum to the old NFSv2 one, as required. */
 		if ((nd->nd_flag & ND_NFSV2) != 0) {
 			if (nd->nd_procnum < NFS_V3NPROCS)
 				procnum = nfsv2_procid[nd->nd_procnum];
 			else
 				procnum = NFSV2PROC_NOOP;
 		}
 
 		/*
 		 * Now only used for the R_DONTRECOVER case, but until that is
 		 * supported within the krpc code, I need to keep a queue of
 		 * outstanding RPCs for nfsv4 client requests.
 		 */
 		if ((nd->nd_flag & ND_NFSV4) && procnum == NFSV4PROC_COMPOUND)
 			rep = malloc(sizeof(struct nfsreq),
 			    M_NFSDREQ, M_WAITOK);
 #ifdef KDTRACE_HOOKS
 		if (dtrace_nfscl_nfs234_start_probe != NULL) {
 			uint32_t probe_id;
 			int probe_procnum;
 
 			if (nd->nd_flag & ND_NFSV4) {
 				probe_id =
 				    nfscl_nfs4_start_probes[nd->nd_procnum];
 				probe_procnum = nd->nd_procnum;
 			} else if (nd->nd_flag & ND_NFSV3) {
 				probe_id = nfscl_nfs3_start_probes[procnum];
 				probe_procnum = procnum;
 			} else {
 				probe_id =
 				    nfscl_nfs2_start_probes[nd->nd_procnum];
 				probe_procnum = procnum;
 			}
 			if (probe_id != 0)
 				(dtrace_nfscl_nfs234_start_probe)
 				    (probe_id, vp, nd->nd_mreq, cred,
 				     probe_procnum);
 		}
 #endif
 	}
 	freeslot = -1;		/* Set to slot that needs to be free'd */
 tryagain:
 	slot = -1;		/* Slot that needs a sequence# increment. */
 	/*
 	 * This timeout specifies when a new socket should be created,
 	 * along with new xid values. For UDP, this should be done
 	 * infrequently, since retransmits of RPC requests should normally
 	 * use the same xid.
 	 */
 	if (nmp == NULL) {
 		if (clp == NULL) {
 			timo.tv_sec = NFSV4_UPCALLTIMEO;
 			timo.tv_usec = 0;
 		} else {
 			timo.tv_sec = NFSV4_CALLBACKTIMEO / 1000;
 			timo.tv_usec = NFSV4_CALLBACKTIMEO * 1000;
 		}
 	} else {
 		if (nrp->nr_sotype != SOCK_DGRAM) {
 			timo.tv_usec = 0;
 			if ((nmp->nm_flag & NFSMNT_NFSV4))
 				timo.tv_sec = INT_MAX;
 			else
 				timo.tv_sec = NFS_TCPTIMEO;
 		} else {
 			if (NFSHASSOFT(nmp)) {
 				/*
 				 * CLSET_RETRIES is set to 2, so this should be
 				 * half of the total timeout required.
 				 */
 				timeo = nmp->nm_retry * nmp->nm_timeo / 2;
 				if (timeo < 1)
 					timeo = 1;
 				timo.tv_sec = timeo / NFS_HZ;
 				timo.tv_usec = (timeo % NFS_HZ) * 1000000 /
 				    NFS_HZ;
 			} else {
 				/* For UDP hard mounts, use a large value. */
 				timo.tv_sec = NFS_MAXTIMEO / NFS_HZ;
 				timo.tv_usec = 0;
 			}
 		}
 
 		if (rep != NULL) {
 			rep->r_flags = 0;
 			rep->r_nmp = nmp;
 			/*
 			 * Chain request into list of outstanding requests.
 			 */
 			NFSLOCKREQ();
 			TAILQ_INSERT_TAIL(&nfsd_reqq, rep, r_chain);
 			NFSUNLOCKREQ();
 		}
 	}
 
 	nd->nd_mrep = NULL;
 	if (clp != NULL && sep != NULL)
 		stat = clnt_bck_call(nrp->nr_client, &ext, procnum,
 		    nd->nd_mreq, &nd->nd_mrep, timo, sep->nfsess_xprt);
 	else if (nextconn_set)
 		/*
 		 * When there are multiple TCP connections, send the
 		 * RPCs with large messages on the alternate TCP
 		 * connection(s) in a round robin fashion.
 		 * The small RPC messages are sent on the default
 		 * TCP connection because they do not require much
 		 * network bandwidth and separating them from the
 		 * large RPC messages avoids them getting "log jammed"
 		 * behind several large RPC messages.
 		 */
 		stat = CLNT_CALL_MBUF(nmp->nm_aconn[nextconn],
 		    &ext, procnum, nd->nd_mreq, &nd->nd_mrep, timo);
 	else
 		stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum,
 		    nd->nd_mreq, &nd->nd_mrep, timo);
 	NFSCL_DEBUG(2, "clnt call=%d\n", stat);
 
 	if (rep != NULL) {
 		/*
 		 * RPC done, unlink the request.
 		 */
 		NFSLOCKREQ();
 		TAILQ_REMOVE(&nfsd_reqq, rep, r_chain);
 		NFSUNLOCKREQ();
 	}
 
 	/*
 	 * If there was a successful reply and a tprintf msg.
 	 * tprintf a response.
 	 */
 	if (stat == RPC_SUCCESS) {
 		error = 0;
 	} else if (stat == RPC_TIMEDOUT) {
 		NFSINCRGLOBAL(nfsstatsv1.rpctimeouts);
 		error = ETIMEDOUT;
 	} else if (stat == RPC_VERSMISMATCH) {
 		NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
 		error = EOPNOTSUPP;
 	} else if (stat == RPC_PROGVERSMISMATCH) {
 		NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
 		error = EPROTONOSUPPORT;
 	} else if (stat == RPC_CANTSEND || stat == RPC_CANTRECV ||
 	     stat == RPC_SYSTEMERROR || stat == RPC_INTR) {
 		/* Check for a session slot that needs to be free'd. */
 		if ((nd->nd_flag & (ND_NFSV41 | ND_HASSLOTID)) ==
 		    (ND_NFSV41 | ND_HASSLOTID) && nmp != NULL &&
 		    nd->nd_procnum != NFSPROC_NULL) {
 			/*
 			 * This should only occur when either the MDS or
 			 * a client has an RPC against a DS fail.
 			 * This happens because these cases use "soft"
 			 * connections that can time out and fail.
 			 * The slot used for this RPC is now in a
 			 * non-deterministic state, but if the slot isn't
 			 * free'd, threads can get stuck waiting for a slot.
 			 */
 			if (sep == NULL)
 				sep = nfsmnt_mdssession(nmp);
 			/*
 			 * Bump the sequence# out of range, so that reuse of
 			 * this slot will result in an NFSERR_SEQMISORDERED
 			 * error and not a bogus cached RPC reply.
 			 */
 			mtx_lock(&sep->nfsess_mtx);
 			sep->nfsess_slotseq[nd->nd_slotid] += 10;
 			sep->nfsess_badslots |= (0x1ULL << nd->nd_slotid);
 			mtx_unlock(&sep->nfsess_mtx);
 			/* And free the slot. */
 			nfsv4_freeslot(sep, nd->nd_slotid, false);
 		}
 		if (stat == RPC_INTR)
 			error = EINTR;
 		else {
 			NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
 			error = ENXIO;
 		}
 	} else {
 		NFSINCRGLOBAL(nfsstatsv1.rpcinvalid);
 		error = EACCES;
 	}
 	if (error) {
 		m_freem(nd->nd_mreq);
 		if (usegssname == 0)
 			AUTH_DESTROY(auth);
 		if (rep != NULL)
 			free(rep, M_NFSDREQ);
 		if (set_sigset)
 			newnfs_restore_sigmask(td, &oldset);
 		return (error);
 	}
 
 	KASSERT(nd->nd_mrep != NULL, ("mrep shouldn't be NULL if no error\n"));
 
 	/*
 	 * Search for any mbufs that are not a multiple of 4 bytes long
 	 * or with m_data not longword aligned.
 	 * These could cause pointer alignment problems, so copy them to
 	 * well aligned mbufs.
 	 */
 	newnfs_realign(&nd->nd_mrep, M_WAITOK);
 	nd->nd_md = nd->nd_mrep;
 	nd->nd_dpos = mtod(nd->nd_md, caddr_t);
 	nd->nd_repstat = 0;
 	if (nd->nd_procnum != NFSPROC_NULL &&
 	    nd->nd_procnum != NFSV4PROC_CBNULL) {
 		/* If sep == NULL, set it to the default in nmp. */
 		if (sep == NULL && nmp != NULL)
 			sep = nfsmnt_mdssession(nmp);
 		/*
 		 * and now the actual NFS xdr.
 		 */
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl);
 		if (nd->nd_repstat >= 10000)
 			NFSCL_DEBUG(1, "proc=%d reps=%d\n", (int)nd->nd_procnum,
 			    (int)nd->nd_repstat);
 
 		/*
 		 * Get rid of the tag, return count and SEQUENCE result for
 		 * NFSv4.
 		 */
 		if ((nd->nd_flag & ND_NFSV4) != 0 && nd->nd_repstat !=
 		    NFSERR_MINORVERMISMATCH) {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			i = fxdr_unsigned(int, *tl);
 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
 			if (error)
 				goto nfsmout;
 			NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 			opcnt = fxdr_unsigned(int, *tl++);
 			i = fxdr_unsigned(int, *tl++);
 			j = fxdr_unsigned(int, *tl);
 			if (j >= 10000)
 				NFSCL_DEBUG(1, "fop=%d fst=%d\n", i, j);
 			/*
 			 * If the first op is Sequence, free up the slot.
 			 */
 			if ((nmp != NULL && i == NFSV4OP_SEQUENCE && j != 0) ||
 			   (clp != NULL && i == NFSV4OP_CBSEQUENCE && j != 0)) {
 				NFSCL_DEBUG(1, "failed seq=%d\n", j);
 				if (sep != NULL && i == NFSV4OP_SEQUENCE &&
 				    j == NFSERR_SEQMISORDERED) {
 					mtx_lock(&sep->nfsess_mtx);
 					sep->nfsess_badslots |=
 					    (0x1ULL << nd->nd_slotid);
 					mtx_unlock(&sep->nfsess_mtx);
 				}
 			}
 			if (((nmp != NULL && i == NFSV4OP_SEQUENCE && j == 0) ||
 			    (clp != NULL && i == NFSV4OP_CBSEQUENCE &&
 			    j == 0)) && sep != NULL) {
 				if (i == NFSV4OP_SEQUENCE)
 					NFSM_DISSECT(tl, uint32_t *,
 					    NFSX_V4SESSIONID +
 					    5 * NFSX_UNSIGNED);
 				else
 					NFSM_DISSECT(tl, uint32_t *,
 					    NFSX_V4SESSIONID +
 					    4 * NFSX_UNSIGNED);
 				mtx_lock(&sep->nfsess_mtx);
 				if (bcmp(tl, sep->nfsess_sessionid,
 				    NFSX_V4SESSIONID) == 0) {
 					tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
 					retseq = fxdr_unsigned(uint32_t, *tl++);
 					slot = fxdr_unsigned(int, *tl++);
 					if ((nd->nd_flag & ND_HASSLOTID) != 0) {
 						if (slot >= NFSV4_SLOTS ||
 						    (i == NFSV4OP_CBSEQUENCE &&
 						     slot >= NFSV4_CBSLOTS)) {
 							printf("newnfs_request:"
 							    " Bogus slot\n");
 							slot = nd->nd_slotid;
 						} else if (slot !=
 						    nd->nd_slotid) {
 						    printf("newnfs_request:"
 							" Wrong session "
 							"srvslot=%d "
 							"slot=%d\n", slot,
 							nd->nd_slotid);
 						    if (i == NFSV4OP_SEQUENCE) {
 							/*
 							 * Mark both slots as
 							 * bad, because we do
 							 * not know if the
 							 * server has advanced
 							 * the sequence# for
 							 * either of them.
 							 */
 							sep->nfsess_badslots |=
 							    (0x1ULL << slot);
 							sep->nfsess_badslots |=
 							    (0x1ULL <<
 							     nd->nd_slotid);
 						    }
 						    slot = nd->nd_slotid;
 						}
 						freeslot = slot;
 					} else if (slot != 0) {
 						printf("newnfs_request: Bad "
 						    "session slot=%d\n", slot);
 						slot = 0;
 					}
 					if (retseq != sep->nfsess_slotseq[slot])
 						printf("retseq diff 0x%x\n",
 						    retseq);
 					retval = fxdr_unsigned(uint32_t, *++tl);
 					if ((retval + 1) < sep->nfsess_foreslots
 					    )
 						sep->nfsess_foreslots = (retval
 						    + 1);
 					else if ((retval + 1) >
 					    sep->nfsess_foreslots)
 						sep->nfsess_foreslots = (retval
 						    < 64) ? (retval + 1) : 64;
 				}
 				mtx_unlock(&sep->nfsess_mtx);
 
 				/* Grab the op and status for the next one. */
 				if (opcnt > 1) {
 					NFSM_DISSECT(tl, uint32_t *,
 					    2 * NFSX_UNSIGNED);
 					i = fxdr_unsigned(int, *tl++);
 					j = fxdr_unsigned(int, *tl);
 				}
 			}
 		}
 		if (nd->nd_repstat != 0) {
 			if (nd->nd_repstat == NFSERR_BADSESSION &&
 			    nmp != NULL && dssep == NULL &&
 			    (nd->nd_flag & ND_NFSV41) != 0) {
 				/*
 				 * If this is a client side MDS RPC, mark
 				 * the MDS session defunct and initiate
 				 * recovery, as required.
 				 * The nfsess_defunct field is protected by
 				 * the NFSLOCKMNT()/nm_mtx lock and not the
 				 * nfsess_mtx lock to simplify its handling,
 				 * for the MDS session. This lock is also
 				 * sufficient for nfsess_sessionid, since it
 				 * never changes in the structure.
 				 */
 				NFSCL_DEBUG(1, "Got badsession\n");
 				NFSLOCKCLSTATE();
 				NFSLOCKMNT(nmp);
 				if (TAILQ_EMPTY(&nmp->nm_sess)) {
 					NFSUNLOCKMNT(nmp);
 					NFSUNLOCKCLSTATE();
 					printf("If server has not rebooted, "
 					    "check NFS clients for unique "
 					    "/etc/hostid's\n");
 					goto out;
 				}
 				sep = NFSMNT_MDSSESSION(nmp);
 				if (bcmp(sep->nfsess_sessionid, nd->nd_sequence,
 				    NFSX_V4SESSIONID) == 0) {
 					printf("Initiate recovery. If server "
 					    "has not rebooted, "
 					    "check NFS clients for unique "
 					    "/etc/hostid's\n");
 					/* Initiate recovery. */
 					sep->nfsess_defunct = 1;
 					NFSCL_DEBUG(1, "Marked defunct\n");
 					if (nmp->nm_clp != NULL) {
 						nmp->nm_clp->nfsc_flags |=
 						    NFSCLFLAGS_RECOVER;
 						wakeup(nmp->nm_clp);
 					}
 				}
 				NFSUNLOCKCLSTATE();
 				/*
 				 * Sleep for up to 1sec waiting for a new
 				 * session.
 				 */
 				mtx_sleep(&nmp->nm_sess, &nmp->nm_mtx, PZERO,
 				    "nfsbadsess", hz);
 				/*
 				 * Get the session again, in case a new one
 				 * has been created during the sleep.
 				 */
 				sep = NFSMNT_MDSSESSION(nmp);
 				NFSUNLOCKMNT(nmp);
 				if ((nd->nd_flag & ND_LOOPBADSESS) != 0) {
 					reterr = nfsv4_sequencelookup(nmp, sep,
 					    &slotpos, &maxslot, &slotseq,
 					    sessionid, true);
 					if (reterr == 0) {
 						/* Fill in new session info. */
 						NFSCL_DEBUG(1,
 						  "Filling in new sequence\n");
 						tl = nd->nd_sequence;
 						bcopy(sessionid, tl,
 						    NFSX_V4SESSIONID);
 						tl += NFSX_V4SESSIONID /
 						    NFSX_UNSIGNED;
 						*tl++ = txdr_unsigned(slotseq);
 						*tl++ = txdr_unsigned(slotpos);
 						*tl = txdr_unsigned(maxslot);
 						nd->nd_slotid = slotpos;
 						nd->nd_flag |= ND_HASSLOTID;
 					}
 					if (reterr == NFSERR_BADSESSION ||
 					    reterr == 0) {
 						NFSCL_DEBUG(1,
 						    "Badsession looping\n");
 						m_freem(nd->nd_mrep);
 						nd->nd_mrep = NULL;
 						goto tryagain;
 					}
 					nd->nd_repstat = reterr;
 					NFSCL_DEBUG(1, "Got err=%d\n", reterr);
 				}
 			}
 			/*
 			 * When clp != NULL, it is a callback and all
 			 * callback operations can be retried for NFSERR_DELAY.
 			 */
 			if (((nd->nd_repstat == NFSERR_DELAY ||
 			      nd->nd_repstat == NFSERR_GRACE) &&
 			     (nd->nd_flag & ND_NFSV4) && (clp != NULL ||
 			     (nd->nd_procnum != NFSPROC_DELEGRETURN &&
 			     nd->nd_procnum != NFSPROC_SETATTR &&
 			     nd->nd_procnum != NFSPROC_READ &&
 			     nd->nd_procnum != NFSPROC_READDS &&
 			     nd->nd_procnum != NFSPROC_WRITE &&
 			     nd->nd_procnum != NFSPROC_WRITEDS &&
 			     nd->nd_procnum != NFSPROC_OPEN &&
 			     nd->nd_procnum != NFSPROC_OPENLAYGET &&
 			     nd->nd_procnum != NFSPROC_CREATE &&
 			     nd->nd_procnum != NFSPROC_CREATELAYGET &&
 			     nd->nd_procnum != NFSPROC_OPENCONFIRM &&
 			     nd->nd_procnum != NFSPROC_OPENDOWNGRADE &&
 			     nd->nd_procnum != NFSPROC_CLOSE &&
 			     nd->nd_procnum != NFSPROC_LOCK &&
 			     nd->nd_procnum != NFSPROC_LOCKU))) ||
 			    (nd->nd_repstat == NFSERR_DELAY &&
 			     (nd->nd_flag & ND_NFSV4) == 0) ||
 			    nd->nd_repstat == NFSERR_RESOURCE ||
 			    nd->nd_repstat == NFSERR_RETRYUNCACHEDREP) {
 				/* Clip at NFS_TRYLATERDEL. */
 				if (timespeccmp(&trylater_delay,
 				    &nfs_trylater_max, >))
 					trylater_delay = nfs_trylater_max;
 				getnanouptime(&waituntil);
 				timespecadd(&waituntil, &trylater_delay,
 				    &waituntil);
 				do {
 					nfs_catnap(PZERO, 0, "nfstry");
 					getnanouptime(&ts);
 				} while (timespeccmp(&ts, &waituntil, <));
 				timespecadd(&trylater_delay, &trylater_delay,
 				    &trylater_delay);	/* Double each time. */
 				if (slot != -1) {
 					mtx_lock(&sep->nfsess_mtx);
 					sep->nfsess_slotseq[slot]++;
 					*nd->nd_slotseq = txdr_unsigned(
 					    sep->nfsess_slotseq[slot]);
 					mtx_unlock(&sep->nfsess_mtx);
 				}
 				m_freem(nd->nd_mrep);
 				nd->nd_mrep = NULL;
 				goto tryagain;
 			}
 
 			/*
 			 * If the File Handle was stale, invalidate the
 			 * lookup cache, just in case.
 			 * (vp != NULL implies a client side call)
 			 */
 			if (nd->nd_repstat == ESTALE && vp != NULL) {
 				cache_purge(vp);
 				if (ncl_call_invalcaches != NULL)
 					(*ncl_call_invalcaches)(vp);
 			}
 		}
 		if ((nd->nd_flag & ND_NFSV4) != 0) {
 			/* Free the slot, as required. */
 			if (freeslot != -1)
 				nfsv4_freeslot(sep, freeslot, false);
 			/*
 			 * If this op is Putfh, throw its results away.
 			 */
 			if (j >= 10000)
 				NFSCL_DEBUG(1, "nop=%d nst=%d\n", i, j);
 			if (nmp != NULL && i == NFSV4OP_PUTFH && j == 0) {
 				NFSM_DISSECT(tl,u_int32_t *,2 * NFSX_UNSIGNED);
 				i = fxdr_unsigned(int, *tl++);
 				j = fxdr_unsigned(int, *tl);
 				if (j >= 10000)
 					NFSCL_DEBUG(1, "n2op=%d n2st=%d\n", i,
 					    j);
 				/*
 				 * All Compounds that do an Op that must
 				 * be in sequence consist of NFSV4OP_PUTFH
 				 * followed by one of these. As such, we
 				 * can determine if the seqid# should be
 				 * incremented, here.
 				 */
 				if ((i == NFSV4OP_OPEN ||
 				     i == NFSV4OP_OPENCONFIRM ||
 				     i == NFSV4OP_OPENDOWNGRADE ||
 				     i == NFSV4OP_CLOSE ||
 				     i == NFSV4OP_LOCK ||
 				     i == NFSV4OP_LOCKU) &&
 				    (j == 0 ||
 				     (j != NFSERR_STALECLIENTID &&
 				      j != NFSERR_STALESTATEID &&
 				      j != NFSERR_BADSTATEID &&
 				      j != NFSERR_BADSEQID &&
 				      j != NFSERR_BADXDR &&	 
 				      j != NFSERR_RESOURCE &&
 				      j != NFSERR_NOFILEHANDLE)))		 
 					nd->nd_flag |= ND_INCRSEQID;
 			}
 			/*
 			 * If this op's status is non-zero, mark
 			 * that there is no more data to process.
 			 * The exception is Setattr, which always has xdr
 			 * when it has failed.
 			 */
 			if (j != 0 && i != NFSV4OP_SETATTR)
 				nd->nd_flag |= ND_NOMOREDATA;
 
 			/*
 			 * If R_DONTRECOVER is set, replace the stale error
 			 * reply, so that recovery isn't initiated.
 			 */
 			if ((nd->nd_repstat == NFSERR_STALECLIENTID ||
 			     nd->nd_repstat == NFSERR_BADSESSION ||
 			     nd->nd_repstat == NFSERR_STALESTATEID) &&
 			    rep != NULL && (rep->r_flags & R_DONTRECOVER))
 				nd->nd_repstat = NFSERR_STALEDONTRECOVER;
 		}
 	}
 out:
 
 #ifdef KDTRACE_HOOKS
 	if (nmp != NULL && dtrace_nfscl_nfs234_done_probe != NULL) {
 		uint32_t probe_id;
 		int probe_procnum;
 
 		if (nd->nd_flag & ND_NFSV4) {
 			probe_id = nfscl_nfs4_done_probes[nd->nd_procnum];
 			probe_procnum = nd->nd_procnum;
 		} else if (nd->nd_flag & ND_NFSV3) {
 			probe_id = nfscl_nfs3_done_probes[procnum];
 			probe_procnum = procnum;
 		} else {
 			probe_id = nfscl_nfs2_done_probes[nd->nd_procnum];
 			probe_procnum = procnum;
 		}
 		if (probe_id != 0)
 			(dtrace_nfscl_nfs234_done_probe)(probe_id, vp,
 			    nd->nd_mreq, cred, probe_procnum, 0);
 	}
 #endif
 
 	m_freem(nd->nd_mreq);
 	if (usegssname == 0)
 		AUTH_DESTROY(auth);
 	if (rep != NULL)
 		free(rep, M_NFSDREQ);
 	if (set_sigset)
 		newnfs_restore_sigmask(td, &oldset);
 	return (0);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	m_freem(nd->nd_mreq);
 	if (usegssname == 0)
 		AUTH_DESTROY(auth);
 	if (rep != NULL)
 		free(rep, M_NFSDREQ);
 	if (set_sigset)
 		newnfs_restore_sigmask(td, &oldset);
 	return (error);
 }
 
 /*
  * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
  * wait for all requests to complete. This is used by forced unmounts
  * to terminate any outstanding RPCs.
  */
 int
 newnfs_nmcancelreqs(struct nfsmount *nmp)
 {
 	struct nfsclds *dsp;
 	struct __rpc_client *cl;
 	int i;
 
 	if (nmp->nm_sockreq.nr_client != NULL)
 		CLNT_CLOSE(nmp->nm_sockreq.nr_client);
 	for (i = 0; i < nmp->nm_aconnect; i++)
 		if (nmp->nm_aconn[i] != NULL)
 			CLNT_CLOSE(nmp->nm_aconn[i]);
 lookformore:
 	NFSLOCKMNT(nmp);
 	TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
 		NFSLOCKDS(dsp);
 		if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
 		    (dsp->nfsclds_flags & NFSCLDS_CLOSED) == 0 &&
 		    dsp->nfsclds_sockp != NULL &&
 		    dsp->nfsclds_sockp->nr_client != NULL) {
 			dsp->nfsclds_flags |= NFSCLDS_CLOSED;
 			cl = dsp->nfsclds_sockp->nr_client;
 			NFSUNLOCKDS(dsp);
 			NFSUNLOCKMNT(nmp);
 			CLNT_CLOSE(cl);
 			goto lookformore;
 		}
 		NFSUNLOCKDS(dsp);
 	}
 	NFSUNLOCKMNT(nmp);
 	return (0);
 }
 
 /*
  * Any signal that can interrupt an NFS operation in an intr mount
  * should be added to this set. SIGSTOP and SIGKILL cannot be masked.
  */
 int newnfs_sig_set[] = {
 	SIGINT,
 	SIGTERM,
 	SIGHUP,
 	SIGKILL,
 	SIGQUIT
 };
 
 /*
  * Check to see if one of the signals in our subset is pending on
  * the process (in an intr mount).
  */
 static int
 nfs_sig_pending(sigset_t set)
 {
 	int i;
 
 	for (i = 0 ; i < nitems(newnfs_sig_set); i++)
 		if (SIGISMEMBER(set, newnfs_sig_set[i]))
 			return (1);
 	return (0);
 }
 
 /*
  * The set/restore sigmask functions are used to (temporarily) overwrite
  * the thread td_sigmask during an RPC call (for example). These are also
  * used in other places in the NFS client that might tsleep().
  */
 void
 newnfs_set_sigmask(struct thread *td, sigset_t *oldset)
 {
 	sigset_t newset;
 	int i;
 	struct proc *p;
 
 	SIGFILLSET(newset);
 	if (td == NULL)
 		td = curthread; /* XXX */
 	p = td->td_proc;
 	/* Remove the NFS set of signals from newset */
 	PROC_LOCK(p);
 	mtx_lock(&p->p_sigacts->ps_mtx);
 	for (i = 0 ; i < nitems(newnfs_sig_set); i++) {
 		/*
 		 * But make sure we leave the ones already masked
 		 * by the process, ie. remove the signal from the
 		 * temporary signalmask only if it wasn't already
 		 * in p_sigmask.
 		 */
 		if (!SIGISMEMBER(td->td_sigmask, newnfs_sig_set[i]) &&
 		    !SIGISMEMBER(p->p_sigacts->ps_sigignore, newnfs_sig_set[i]))
 			SIGDELSET(newset, newnfs_sig_set[i]);
 	}
 	mtx_unlock(&p->p_sigacts->ps_mtx);
 	kern_sigprocmask(td, SIG_SETMASK, &newset, oldset,
 	    SIGPROCMASK_PROC_LOCKED);
 	PROC_UNLOCK(p);
 }
 
 void
 newnfs_restore_sigmask(struct thread *td, sigset_t *set)
 {
 	if (td == NULL)
 		td = curthread; /* XXX */
 	kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0);
 }
 
 /*
  * NFS wrapper to msleep(), that shoves a new p_sigmask and restores the
  * old one after msleep() returns.
  */
 int
 newnfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, char *wmesg, int timo)
 {
 	sigset_t oldset;
 	int error;
 
 	if ((priority & PCATCH) == 0)
 		return msleep(ident, mtx, priority, wmesg, timo);
 	if (td == NULL)
 		td = curthread; /* XXX */
 	newnfs_set_sigmask(td, &oldset);
 	error = msleep(ident, mtx, priority, wmesg, timo);
 	newnfs_restore_sigmask(td, &oldset);
 	return (error);
 }
 
 /*
  * Test for a termination condition pending on the process.
  * This is used for NFSMNT_INT mounts.
  */
 int
 newnfs_sigintr(struct nfsmount *nmp, struct thread *td)
 {
 	struct proc *p;
 	sigset_t tmpset;
 
 	/* Terminate all requests while attempting a forced unmount. */
 	if (NFSCL_FORCEDISM(nmp->nm_mountp))
 		return (EIO);
 	if (!(nmp->nm_flag & NFSMNT_INT))
 		return (0);
 	if (td == NULL)
 		return (0);
 	p = td->td_proc;
 	PROC_LOCK(p);
 	tmpset = p->p_siglist;
 	SIGSETOR(tmpset, td->td_siglist);
 	SIGSETNAND(tmpset, td->td_sigmask);
 	mtx_lock(&p->p_sigacts->ps_mtx);
 	SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
 	mtx_unlock(&p->p_sigacts->ps_mtx);
 	if ((SIGNOTEMPTY(p->p_siglist) || SIGNOTEMPTY(td->td_siglist))
 	    && nfs_sig_pending(tmpset)) {
 		PROC_UNLOCK(p);
 		return (EINTR);
 	}
 	PROC_UNLOCK(p);
 	return (0);
 }
 
 static int
 nfs_msg(struct thread *td, const char *server, const char *msg, int error)
 {
 	struct proc *p;
 
 	p = td ? td->td_proc : NULL;
 	if (error) {
 		tprintf(p, LOG_INFO, "nfs server %s: %s, error %d\n",
 		    server, msg, error);
 	} else {
 		tprintf(p, LOG_INFO, "nfs server %s: %s\n", server, msg);
 	}
 	return (0);
 }
 
 static void
 nfs_down(struct nfsmount *nmp, struct thread *td, const char *msg,
     int error, int flags)
 {
 	if (nmp == NULL)
 		return;
 	mtx_lock(&nmp->nm_mtx);
 	if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) {
 		nmp->nm_state |= NFSSTA_TIMEO;
 		mtx_unlock(&nmp->nm_mtx);
 		vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
 		    VQ_NOTRESP, 0);
 	} else
 		mtx_unlock(&nmp->nm_mtx);
 	mtx_lock(&nmp->nm_mtx);
 	if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) {
 		nmp->nm_state |= NFSSTA_LOCKTIMEO;
 		mtx_unlock(&nmp->nm_mtx);
 		vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
 		    VQ_NOTRESPLOCK, 0);
 	} else
 		mtx_unlock(&nmp->nm_mtx);
 	nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error);
 }
 
 static void
 nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg,
     int flags, int tprintfmsg)
 {
 	if (nmp == NULL)
 		return;
 	if (tprintfmsg) {
 		nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
 	}
 
 	mtx_lock(&nmp->nm_mtx);
 	if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) {
 		nmp->nm_state &= ~NFSSTA_TIMEO;
 		mtx_unlock(&nmp->nm_mtx);
 		vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
 		    VQ_NOTRESP, 1);
 	} else
 		mtx_unlock(&nmp->nm_mtx);
 
 	mtx_lock(&nmp->nm_mtx);
 	if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
 		nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
 		mtx_unlock(&nmp->nm_mtx);
 		vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
 		    VQ_NOTRESPLOCK, 1);
 	} else
 		mtx_unlock(&nmp->nm_mtx);
 }
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 87362f2e744f..1b0011760d10 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1,9357 +1,9397 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Rick Macklem at The University of Guelph.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  */
 
 #include <sys/cdefs.h>
 /*
  * Rpc op calls, generally called from the vnode op calls or through the
  * buffer cache, for NFS v2, 3 and 4.
  * These do not normally make any changes to vnode arguments or use
  * structures that might change between the VFS variants. The returned
  * arguments are all at the end, after the NFSPROC_T *p one.
  */
 
 #include "opt_inet6.h"
 
 #include <fs/nfs/nfsport.h>
 #include <fs/nfsclient/nfs.h>
 #include <sys/extattr.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
 
 SYSCTL_DECL(_vfs_nfs);
 
 static int	nfsignore_eexist = 0;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, ignore_eexist, CTLFLAG_RW,
     &nfsignore_eexist, 0, "NFS ignore EEXIST replies for mkdir/symlink");
 
 static int	nfscl_dssameconn = 0;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, dssameconn, CTLFLAG_RW,
     &nfscl_dssameconn, 0, "Use same TCP connection to multiple DSs");
 
 static uint64_t nfs_maxcopyrange = SSIZE_MAX;
 SYSCTL_U64(_vfs_nfs, OID_AUTO, maxcopyrange, CTLFLAG_RW,
     &nfs_maxcopyrange, 0, "Max size of a Copy so RPC times reasonable");
 
 /*
  * Global variables
  */
 extern struct nfsstatsv1 nfsstatsv1;
 extern int nfs_numnfscbd;
 extern struct timeval nfsboottime;
 extern u_int32_t newnfs_false, newnfs_true;
 extern nfstype nfsv34_type[9];
 extern int nfsrv_useacl;
 extern char nfsv4_callbackaddr[INET6_ADDRSTRLEN];
 extern int nfscl_debuglevel;
 extern int nfs_pnfsiothreads;
 extern u_long sb_max_adj;
 NFSCLSTATEMUTEX;
 int nfstest_outofseq = 0;
 int nfscl_assumeposixlocks = 1;
 int nfscl_enablecallb = 0;
 short nfsv4_cbport = NFSV4_CBPORT;
 int nfstest_openallsetattr = 0;
 
 #define	DIRHDSIZ	offsetof(struct dirent, d_name)
 
 /*
  * nfscl_getsameserver() can return one of three values:
  * NFSDSP_USETHISSESSION - Use this session for the DS.
  * NFSDSP_SEQTHISSESSION - Use the nfsclds_sequence field of this dsp for new
  *     session.
  * NFSDSP_NOTFOUND - No matching server was found.
  */
 enum nfsclds_state {
 	NFSDSP_USETHISSESSION = 0,
 	NFSDSP_SEQTHISSESSION = 1,
 	NFSDSP_NOTFOUND = 2,
 };
 
 /*
  * Do a write RPC on a DS data file, using this structure for the arguments,
  * so that this function can be executed by a separate kernel process.
  */
 struct nfsclwritedsdorpc {
 	int			done;
 	int			inprog;
 	struct task		tsk;
 	struct vnode		*vp;
 	int			iomode;
 	int			must_commit;
 	nfsv4stateid_t		*stateidp;
 	struct nfsclds		*dsp;
 	uint64_t		off;
 	int			len;
 #ifdef notyet
 	int			advise;
 #endif
 	struct nfsfh		*fhp;
 	struct mbuf		*m;
 	int			vers;
 	int			minorvers;
 	struct ucred		*cred;
 	NFSPROC_T		*p;
 	int			err;
 };
 
 static int nfsrpc_setattrrpc(vnode_t , struct vattr *, nfsv4stateid_t *,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, int *);
 static int nfsrpc_readrpc(vnode_t , struct uio *, struct ucred *,
     nfsv4stateid_t *, NFSPROC_T *, struct nfsvattr *, int *);
 static int nfsrpc_writerpc(vnode_t , struct uio *, int *, int *,
     struct ucred *, nfsv4stateid_t *, NFSPROC_T *, struct nfsvattr *, int *,
     int);
 static int nfsrpc_deallocaterpc(vnode_t, off_t, off_t, nfsv4stateid_t *,
     struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_createv23(vnode_t , char *, int, struct vattr *,
     nfsquad_t, int, struct ucred *, NFSPROC_T *, struct nfsvattr *,
     struct nfsvattr *, struct nfsfh **, int *, int *);
 static int nfsrpc_createv4(vnode_t , char *, int, struct vattr *,
     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **, struct ucred *,
     NFSPROC_T *, struct nfsvattr *, struct nfsvattr *, struct nfsfh **, int *,
     int *, int *);
 static int nfsrpc_locku(struct nfsrv_descript *, struct nfsmount *,
     struct nfscllockowner *, u_int64_t, u_int64_t,
     u_int32_t, struct ucred *, NFSPROC_T *, int);
 static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
     struct acl *, nfsv4stateid_t *);
 static int nfsrpc_layouterror(struct nfsmount *, uint8_t *, int, uint64_t,
     uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *, uint32_t,
     uint32_t, char *);
 static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
     uint32_t, uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
     struct ucred *, NFSPROC_T *);
 static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
     struct sockaddr_in6 *, sa_family_t, int, int, struct nfsclds **,
     NFSPROC_T *);
 static void nfscl_initsessionslots(struct nfsclsession *);
 static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
     struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *,
     NFSPROC_T *);
 static int nfscl_dofflayoutio(vnode_t, struct uio *, int *, int *, int *,
     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
     struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
     struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
     struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
     struct ucred *, NFSPROC_T *);
 static int nfsrpc_writeds(vnode_t, struct uio *, int *, int *,
     nfsv4stateid_t *, struct nfsclds *, uint64_t, int,
     struct nfsfh *, int, int, int, int, struct ucred *, NFSPROC_T *);
 static int nfsio_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
     struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
     struct nfsclwritedsdorpc *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
     struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
     struct ucred *, NFSPROC_T *);
 static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
     struct nfsclds *, struct nfsclds **, uint32_t *);
 static int nfsio_commitds(vnode_t, uint64_t, int, struct nfsclds *,
     struct nfsfh *, int, int, struct nfsclwritedsdorpc *, struct ucred *,
     NFSPROC_T *);
 static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
     struct nfsfh *, int, int, struct ucred *, NFSPROC_T *);
 #ifdef notyet
 static int nfsio_adviseds(vnode_t, uint64_t, int, int, struct nfsclds *,
     struct nfsfh *, int, int, struct nfsclwritedsdorpc *, struct ucred *,
     NFSPROC_T *);
 static int nfsrpc_adviseds(vnode_t, uint64_t, int, int, struct nfsclds *,
     struct nfsfh *, int, int, struct ucred *, NFSPROC_T *);
 #endif
 static int nfsrpc_allocaterpc(vnode_t, off_t, off_t, nfsv4stateid_t *,
     struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
 static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
     uint64_t, uint64_t, nfsv4stateid_t *, int, int, int);
 static int nfsrv_parseug(struct nfsrv_descript *, int, uid_t *, gid_t *,
     NFSPROC_T *);
 static int nfsrv_parselayoutget(struct nfsmount *, struct nfsrv_descript *,
     nfsv4stateid_t *, int *, struct nfsclflayouthead *);
 static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *,
     int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
     struct nfscldeleg **, struct ucred *, NFSPROC_T *);
 static int nfsrpc_getcreatelayout(vnode_t, char *, int, struct vattr *,
     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
     struct nfsfh **, int *, int *, int *);
 static int nfsrpc_openlayoutrpc(struct nfsmount *, vnode_t, u_int8_t *,
     int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
     struct nfscldeleg **, nfsv4stateid_t *, int, int, int, int *,
     struct nfsclflayouthead *, int *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_createlayout(vnode_t, char *, int, struct vattr *,
     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
     struct nfsfh **, int *, int *, int *, nfsv4stateid_t *,
     int, int, int, int *, struct nfsclflayouthead *, int *);
 static int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t,
     uint64_t, uint64_t, int, int, nfsv4stateid_t *, int *,
     struct nfsclflayouthead *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *,
     int, nfsv4stateid_t *, int, uint32_t *, struct nfscllayout **,
     struct nfsclflayouthead *, int, int, int *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_copyrpc(vnode_t, off_t, vnode_t, off_t, size_t *,
     nfsv4stateid_t *, nfsv4stateid_t *, struct nfsvattr *, int *,
     struct nfsvattr *, int *, bool, int *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_seekrpc(vnode_t, off_t *, nfsv4stateid_t *, bool *,
     int, struct nfsvattr *, int *, struct ucred *);
 static struct mbuf *nfsm_split(struct mbuf *, uint64_t);
 static void nfscl_statfs(struct vnode *, struct ucred *, NFSPROC_T *);
 
 int nfs_pnfsio(task_fn_t *, void *);
 
 /*
  * nfs null call from vfs.
  */
 int
 nfsrpc_null(vnode_t vp, struct ucred *cred, NFSPROC_T *p)
 {
 	int error;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 
 	NFSCL_REQSTART(nd, NFSPROC_NULL, vp, NULL);
 	error = nfscl_request(nd, vp, p, cred);
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs access rpc op.
  * For nfs version 3 and 4, use the access rpc to check accessibility. If file
  * modes are changed on the server, accesses might still fail later.
  */
 int
 nfsrpc_access(vnode_t vp, int acmode, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	int error;
 	u_int32_t mode, rmode;
 
 	if (acmode & VREAD)
 		mode = NFSACCESS_READ;
 	else
 		mode = 0;
 	if (vp->v_type == VDIR) {
 		if (acmode & VWRITE)
 			mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND |
 				 NFSACCESS_DELETE);
 		if (acmode & VEXEC)
 			mode |= NFSACCESS_LOOKUP;
 	} else {
 		if (acmode & VWRITE)
 			mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND);
 		if (acmode & VEXEC)
 			mode |= NFSACCESS_EXECUTE;
 	}
 
 	/*
 	 * Now, just call nfsrpc_accessrpc() to do the actual RPC.
 	 */
 	error = nfsrpc_accessrpc(vp, mode, cred, p, nap, attrflagp, &rmode);
 
 	/*
 	 * The NFS V3 spec does not clarify whether or not
 	 * the returned access bits can be a superset of
 	 * the ones requested, so...
 	 */
 	if (!error && (rmode & mode) != mode)
 		error = EACCES;
 	return (error);
 }
 
 /*
  * The actual rpc, separated out for Darwin.
  */
 int
 nfsrpc_accessrpc(vnode_t vp, u_int32_t mode, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, u_int32_t *rmodep)
 {
 	u_int32_t *tl;
 	u_int32_t supported, rmode;
 	int error;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	struct nfsmount *nmp;
 	struct nfsnode *np;
 
 	*attrflagp = 0;
 	supported = mode;
 	nmp = VFSTONFS(vp->v_mount);
 	np = VTONFS(vp);
 	if ((nmp->nm_privflag & NFSMNTP_FAKEROOTFH) != 0 &&
 	    nmp->nm_fhsize == 0) {
 		/* Attempt to get the actual root file handle. */
 		error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp), cred, p);
 		if (error != 0)
 			return (EACCES);
 		if (np->n_fhp->nfh_len == NFSX_FHMAX + 1)
 			nfscl_statfs(vp, cred, p);
 	}
 	NFSCL_REQSTART(nd, NFSPROC_ACCESS, vp, cred);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(mode);
 	if (nd->nd_flag & ND_NFSV4) {
 		/*
 		 * And do a Getattr op.
 		 */
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSGETATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV3) {
 		error = nfscl_postop_attr(nd, nap, attrflagp);
 		if (error)
 			goto nfsmout;
 	}
 	if (!nd->nd_repstat) {
 		if (nd->nd_flag & ND_NFSV4) {
 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			supported = fxdr_unsigned(u_int32_t, *tl++);
 		} else {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		}
 		rmode = fxdr_unsigned(u_int32_t, *tl);
 		if (nd->nd_flag & ND_NFSV4)
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 
 		/*
 		 * It's not obvious what should be done about
 		 * unsupported access modes. For now, be paranoid
 		 * and clear the unsupported ones.
 		 */
 		rmode &= supported;
 		*rmodep = rmode;
 	} else
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs open rpc
  */
 int
 nfsrpc_open(vnode_t vp, int amode, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsclopen *op;
 	struct nfscldeleg *dp;
 	struct nfsfh *nfhp;
 	struct nfsnode *np = VTONFS(vp);
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	u_int32_t mode, clidrev;
 	int ret, newone, error, expireret = 0, retrycnt;
 
 	/*
 	 * For NFSv4, Open Ops are only done on Regular Files.
 	 */
 	if (vp->v_type != VREG)
 		return (0);
 	mode = 0;
 	if (amode & FREAD)
 		mode |= NFSV4OPEN_ACCESSREAD;
 	if (amode & FWRITE)
 		mode |= NFSV4OPEN_ACCESSWRITE;
 	nfhp = np->n_fhp;
 
 	retrycnt = 0;
 	do {
 	    dp = NULL;
 	    error = nfscl_open(vp, nfhp->nfh_fh, nfhp->nfh_len, mode, 1,
 		cred, p, NULL, &op, &newone, &ret, 1, true);
 	    if (error) {
 		return (error);
 	    }
 	    if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	    else
 		clidrev = 0;
 	    if (ret == NFSCLOPEN_DOOPEN) {
 		if (np->n_v4 != NULL) {
 			/*
 			 * For the first attempt, try and get a layout, if
 			 * pNFS is enabled for the mount.
 			 */
 			if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
 			    nfs_numnfscbd == 0 ||
 			    (np->n_flag & NNOLAYOUT) != 0 || retrycnt > 0)
 				error = nfsrpc_openrpc(nmp, vp,
 				    np->n_v4->n4_data,
 				    np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
 				    np->n_fhp->nfh_len, mode, op,
 				    NFS4NODENAME(np->n_v4),
 				    np->n_v4->n4_namelen,
 				    &dp, 0, 0x0, cred, p, 0, 0);
 			else
 				error = nfsrpc_getopenlayout(nmp, vp,
 				    np->n_v4->n4_data,
 				    np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
 				    np->n_fhp->nfh_len, mode, op,
 				    NFS4NODENAME(np->n_v4),
 				    np->n_v4->n4_namelen, &dp, cred, p);
 			if (dp != NULL) {
 				NFSLOCKNODE(np);
 				np->n_flag &= ~NDELEGMOD;
 				/*
 				 * Invalidate the attribute cache, so that
 				 * attributes that pre-date the issue of a
 				 * delegation are not cached, since the
 				 * cached attributes will remain valid while
 				 * the delegation is held.
 				 */
 				NFSINVALATTRCACHE(np);
 				NFSUNLOCKNODE(np);
 				(void) nfscl_deleg(nmp->nm_mountp,
 				    op->nfso_own->nfsow_clp,
 				    nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp);
 			}
 		} else if (NFSHASNFSV4N(nmp)) {
 			/*
 			 * For the first attempt, try and get a layout, if
 			 * pNFS is enabled for the mount.
 			 */
 			if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
 			    nfs_numnfscbd == 0 ||
 			    (np->n_flag & NNOLAYOUT) != 0 || retrycnt > 0)
 				error = nfsrpc_openrpc(nmp, vp, nfhp->nfh_fh,
 				    nfhp->nfh_len, nfhp->nfh_fh, nfhp->nfh_len,
 				    mode, op, NULL, 0, &dp, 0, 0x0, cred, p, 0,
 				    0);
 			else
 				error = nfsrpc_getopenlayout(nmp, vp,
 				    nfhp->nfh_fh, nfhp->nfh_len, nfhp->nfh_fh,
 				    nfhp->nfh_len, mode, op, NULL, 0, &dp,
 				    cred, p);
 			if (dp != NULL) {
 				NFSLOCKNODE(np);
 				np->n_flag &= ~NDELEGMOD;
 				/*
 				 * Invalidate the attribute cache, so that
 				 * attributes that pre-date the issue of a
 				 * delegation are not cached, since the
 				 * cached attributes will remain valid while
 				 * the delegation is held.
 				 */
 				NFSINVALATTRCACHE(np);
 				NFSUNLOCKNODE(np);
 				(void) nfscl_deleg(nmp->nm_mountp,
 				    op->nfso_own->nfsow_clp,
 				    nfhp->nfh_fh, nfhp->nfh_len, cred, p, &dp);
 			}
 		} else {
 			error = EIO;
 		}
 		newnfs_copyincred(cred, &op->nfso_cred);
 	    } else if (ret == NFSCLOPEN_SETCRED)
 		/*
 		 * This is a new local open on a delegation. It needs
 		 * to have credentials so that an open can be done
 		 * against the server during recovery.
 		 */
 		newnfs_copyincred(cred, &op->nfso_cred);
 
 	    /*
 	     * nfso_opencnt is the count of how many VOP_OPEN()s have
 	     * been done on this Open successfully and a VOP_CLOSE()
 	     * is expected for each of these.
 	     * If error is non-zero, don't increment it, since the Open
 	     * hasn't succeeded yet.
 	     */
 	    if (!error) {
 		op->nfso_opencnt++;
 		if (NFSHASNFSV4N(nmp) && NFSHASONEOPENOWN(nmp)) {
 		    NFSLOCKNODE(np);
 		    np->n_openstateid = op;
 		    NFSUNLOCKNODE(np);
 		}
 	    }
 	    nfscl_openrelease(nmp, op, error, newone);
 	    if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 		error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		error == NFSERR_BADSESSION) {
 		(void) nfs_catnap(PZERO, error, "nfs_open");
 	    } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
 		&& clidrev != 0) {
 		expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		retrycnt++;
 	    }
 	} while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 	    error == NFSERR_BADSESSION ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 /*
  * the actual open rpc
  */
 int
 nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, int fhlen,
     u_int8_t *newfhp, int newfhlen, u_int32_t mode, struct nfsclopen *op,
     u_int8_t *name, int namelen, struct nfscldeleg **dpp,
     int reclaim, u_int32_t delegtype, struct ucred *cred, NFSPROC_T *p,
     int syscred, int recursed)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfscldeleg *dp, *ndp = NULL;
 	struct nfsvattr nfsva;
 	u_int32_t rflags, deleg;
 	nfsattrbit_t attrbits;
 	int error, ret, acesize, limitby;
 	struct nfsclsession *tsep;
 
 	dp = *dpp;
 	*dpp = NULL;
 	nfscl_reqstart(nd, NFSPROC_OPEN, nmp, nfhp, fhlen, NULL, NULL, 0, 0,
 	    cred);
 	NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
 	*tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	(void) nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
 	if (reclaim) {
 		*tl = txdr_unsigned(NFSV4OPEN_CLAIMPREVIOUS);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(delegtype);
 	} else {
 		if (dp != NULL) {
 			if (NFSHASNFSV4N(nmp)) {
 				*tl = txdr_unsigned(
 				    NFSV4OPEN_CLAIMDELEGATECURFH);
 				NFSLOCKMNT(nmp);
 				if ((nmp->nm_privflag & NFSMNTP_BUGGYFBSDSRV) !=
 				    0) {
 					NFSUNLOCKMNT(nmp);
 					/*
 					 * Add a stateID argument to make old
 					 * broken FreeBSD NFSv4.1/4.2 servers
 					 * happy.
 					 */
 					NFSM_BUILD(tl, uint32_t *,NFSX_STATEID);
 					*tl++ = 0;
 					*tl++ = dp->nfsdl_stateid.other[0];
 					*tl++ = dp->nfsdl_stateid.other[1];
 					*tl = dp->nfsdl_stateid.other[2];
 				} else
 					NFSUNLOCKMNT(nmp);
 			} else {
 				*tl = txdr_unsigned(NFSV4OPEN_CLAIMDELEGATECUR);
 				NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 				*tl++ = dp->nfsdl_stateid.seqid;
 				*tl++ = dp->nfsdl_stateid.other[0];
 				*tl++ = dp->nfsdl_stateid.other[1];
 				*tl = dp->nfsdl_stateid.other[2];
 				(void)nfsm_strtom(nd, name, namelen);
 			}
 		} else if (NFSHASNFSV4N(nmp)) {
 			*tl = txdr_unsigned(NFSV4OPEN_CLAIMFH);
 		} else {
 			*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
 			(void)nfsm_strtom(nd, name, namelen);
 		}
 	}
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSZERO_ATTRBIT(&attrbits);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
 	(void) nfsrv_putattrbit(nd, &attrbits);
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
 	if (nd->nd_repstat == 0 || (nd->nd_repstat == NFSERR_DELAY &&
 	    reclaim != 0 && (nd->nd_flag & ND_NOMOREDATA) == 0)) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 		    6 * NFSX_UNSIGNED);
 		op->nfso_stateid.seqid = *tl++;
 		op->nfso_stateid.other[0] = *tl++;
 		op->nfso_stateid.other[1] = *tl++;
 		op->nfso_stateid.other[2] = *tl;
 		rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		if (error)
 			goto nfsmout;
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		deleg = fxdr_unsigned(u_int32_t, *tl);
 		if (deleg == NFSV4OPEN_DELEGATEREAD ||
 		    deleg == NFSV4OPEN_DELEGATEWRITE) {
 			if (!(op->nfso_own->nfsow_clp->nfsc_flags &
 			      NFSCLFLAGS_FIRSTDELEG))
 				op->nfso_own->nfsow_clp->nfsc_flags |=
 				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
 			ndp = malloc(
 			    sizeof (struct nfscldeleg) + newfhlen,
 			    M_NFSCLDELEG, M_WAITOK);
 			LIST_INIT(&ndp->nfsdl_owner);
 			LIST_INIT(&ndp->nfsdl_lock);
 			ndp->nfsdl_clp = op->nfso_own->nfsow_clp;
 			ndp->nfsdl_fhlen = newfhlen;
 			NFSBCOPY(newfhp, ndp->nfsdl_fh, newfhlen);
 			newnfs_copyincred(cred, &ndp->nfsdl_cred);
 			nfscl_lockinit(&ndp->nfsdl_rwlock);
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 			    NFSX_UNSIGNED);
 			ndp->nfsdl_stateid.seqid = *tl++;
 			ndp->nfsdl_stateid.other[0] = *tl++;
 			ndp->nfsdl_stateid.other[1] = *tl++;
 			ndp->nfsdl_stateid.other[2] = *tl++;
 			ret = fxdr_unsigned(int, *tl);
 			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
 				ndp->nfsdl_flags = NFSCLDL_WRITE;
 				/*
 				 * Indicates how much the file can grow.
 				 */
 				NFSM_DISSECT(tl, u_int32_t *,
 				    3 * NFSX_UNSIGNED);
 				limitby = fxdr_unsigned(int, *tl++);
 				switch (limitby) {
 				case NFSV4OPEN_LIMITSIZE:
 					ndp->nfsdl_sizelimit = fxdr_hyper(tl);
 					break;
 				case NFSV4OPEN_LIMITBLOCKS:
 					ndp->nfsdl_sizelimit =
 					    fxdr_unsigned(u_int64_t, *tl++);
 					ndp->nfsdl_sizelimit *=
 					    fxdr_unsigned(u_int64_t, *tl);
 					break;
 				default:
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 			} else {
 				ndp->nfsdl_flags = NFSCLDL_READ;
 			}
 			if (ret)
 				ndp->nfsdl_flags |= NFSCLDL_RECALL;
 			error = nfsrv_dissectace(nd, &ndp->nfsdl_ace, false,
 			    &ret, &acesize, p);
 			if (error)
 				goto nfsmout;
 		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		/* If the 2nd element == NFS_OK, the Getattr succeeded. */
 		if (*++tl == 0) {
 			KASSERT(nd->nd_repstat == 0,
 			    ("nfsrpc_openrpc: Getattr repstat"));
 			error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 			    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 			    NULL, NULL, NULL, p, cred);
 			if (error)
 				goto nfsmout;
 		}
 		if (ndp != NULL) {
 			if (reclaim != 0 && dp != NULL) {
 				ndp->nfsdl_change = dp->nfsdl_change;
 				ndp->nfsdl_modtime = dp->nfsdl_modtime;
 				ndp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 			} else if (nd->nd_repstat == 0) {
 				ndp->nfsdl_change = nfsva.na_filerev;
 				ndp->nfsdl_modtime = nfsva.na_mtime;
 				ndp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 			} else
 				ndp->nfsdl_flags |= NFSCLDL_RECALL;
 		}
 		nd->nd_repstat = 0;
 		if (!reclaim && (rflags & NFSV4OPEN_RESULTCONFIRM)) {
 		    do {
 			ret = nfsrpc_openconfirm(vp, newfhp, newfhlen, op,
 			    cred, p);
 			if (ret == NFSERR_DELAY)
 			    (void) nfs_catnap(PZERO, ret, "nfs_open");
 		    } while (ret == NFSERR_DELAY);
 		    error = ret;
 		}
 		if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) ||
 		    nfscl_assumeposixlocks)
 		    op->nfso_posixlock = 1;
 		else
 		    op->nfso_posixlock = 0;
 
 		/*
 		 * If the server is handing out delegations, but we didn't
 		 * get one because an OpenConfirm was required, try the
 		 * Open again, to get a delegation. This is a harmless no-op,
 		 * from a server's point of view.
 		 */
 		if (!reclaim && (rflags & NFSV4OPEN_RESULTCONFIRM) &&
 		    (op->nfso_own->nfsow_clp->nfsc_flags & NFSCLFLAGS_GOTDELEG)
 		    && !error && dp == NULL && ndp == NULL && !recursed) {
 		    do {
 			ret = nfsrpc_openrpc(nmp, vp, nfhp, fhlen, newfhp,
 			    newfhlen, mode, op, name, namelen, &ndp, 0, 0x0,
 			    cred, p, syscred, 1);
 			if (ret == NFSERR_DELAY)
 			    (void) nfs_catnap(PZERO, ret, "nfs_open2");
 		    } while (ret == NFSERR_DELAY);
 		    if (ret) {
 			if (ndp != NULL) {
 				free(ndp, M_NFSCLDELEG);
 				ndp = NULL;
 			}
 			if (ret == NFSERR_STALECLIENTID ||
 			    ret == NFSERR_STALEDONTRECOVER ||
 			    ret == NFSERR_BADSESSION)
 				error = ret;
 		    }
 		}
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	if (error == NFSERR_STALECLIENTID)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	if (!error)
 		*dpp = ndp;
 	else if (ndp != NULL)
 		free(ndp, M_NFSCLDELEG);
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * open downgrade rpc
  */
 int
 nfsrpc_opendowngrade(vnode_t vp, u_int32_t mode, struct nfsclopen *op,
     struct ucred *cred, NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
 	NFSCL_REQSTART(nd, NFSPROC_OPENDOWNGRADE, vp, cred);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 3 * NFSX_UNSIGNED);
 	if (NFSHASNFSV4N(VFSTONFS(vp->v_mount)))
 		*tl++ = 0;
 	else
 		*tl++ = op->nfso_stateid.seqid;
 	*tl++ = op->nfso_stateid.other[0];
 	*tl++ = op->nfso_stateid.other[1];
 	*tl++ = op->nfso_stateid.other[2];
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
 	*tl = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
 	if (!nd->nd_repstat) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 		op->nfso_stateid.seqid = *tl++;
 		op->nfso_stateid.other[0] = *tl++;
 		op->nfso_stateid.other[1] = *tl++;
 		op->nfso_stateid.other[2] = *tl;
 	}
 	if (nd->nd_repstat && error == 0)
 		error = nd->nd_repstat;
 	if (error == NFSERR_STALESTATEID)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * V4 Close operation.
  */
 int
 nfsrpc_close(vnode_t vp, int doclose, NFSPROC_T *p)
 {
 	struct nfsclclient *clp;
 	int error;
 
 	if (vp->v_type != VREG)
 		return (0);
 	if (doclose)
 		error = nfscl_doclose(vp, &clp, p);
 	else {
 		error = nfscl_getclose(vp, &clp);
 		if (error == 0)
 			nfscl_clientrelease(clp);
 	}
 	return (error);
 }
 
 /*
  * Close the open.
  */
 int
 nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p,
     bool loop_on_delayed, bool freeop)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfscllockowner *lp, *nlp;
 	struct nfscllock *lop, *nlop;
 	struct ucred *tcred;
 	u_int64_t off = 0, len = 0;
 	u_int32_t type = NFSV4LOCKT_READ;
 	int error, do_unlock, trycnt;
 
 	tcred = newnfs_getcred();
 	newnfs_copycred(&op->nfso_cred, tcred);
 	/*
 	 * (Theoretically this could be done in the same
 	 *  compound as the close, but having multiple
 	 *  sequenced Ops in the same compound might be
 	 *  too scary for some servers.)
 	 */
 	if (op->nfso_posixlock) {
 		off = 0;
 		len = NFS64BITSSET;
 		type = NFSV4LOCKT_READ;
 	}
 
 	/*
 	 * Since this function is only called from VOP_INACTIVE(), no
 	 * other thread will be manipulating this Open. As such, the
 	 * lock lists are not being changed by other threads, so it should
 	 * be safe to do this without locking.
 	 */
 	LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
 		do_unlock = 1;
 		LIST_FOREACH_SAFE(lop, &lp->nfsl_lock, nfslo_list, nlop) {
 			if (op->nfso_posixlock == 0) {
 				off = lop->nfslo_first;
 				len = lop->nfslo_end - lop->nfslo_first;
 				if (lop->nfslo_type == F_WRLCK)
 					type = NFSV4LOCKT_WRITE;
 				else
 					type = NFSV4LOCKT_READ;
 			}
 			if (do_unlock) {
 				trycnt = 0;
 				do {
 					error = nfsrpc_locku(nd, nmp, lp, off,
 					    len, type, tcred, p, 0);
 					if ((nd->nd_repstat == NFSERR_GRACE ||
 					    nd->nd_repstat == NFSERR_DELAY) &&
 					    error == 0)
 						(void) nfs_catnap(PZERO,
 						    (int)nd->nd_repstat,
 						    "nfs_close");
 				} while ((nd->nd_repstat == NFSERR_GRACE ||
 				    nd->nd_repstat == NFSERR_DELAY) &&
 				    error == 0 && trycnt++ < 5);
 				if (op->nfso_posixlock)
 					do_unlock = 0;
 			}
 			nfscl_freelock(lop, 0);
 		}
 		/*
 		 * Do a ReleaseLockOwner.
 		 * The lock owner name nfsl_owner may be used by other opens for
 		 * other files but the lock_owner4 name that nfsrpc_rellockown()
 		 * puts on the wire has the file handle for this file appended
 		 * to it, so it can be done now.
 		 */
 		(void)nfsrpc_rellockown(nmp, lp, lp->nfsl_open->nfso_fh,
 		    lp->nfsl_open->nfso_fhlen, tcred, p);
 	}
 
 	/*
 	 * There could be other Opens for different files on the same
 	 * OpenOwner, so locking is required.
 	 */
 	NFSLOCKCLSTATE();
 	nfscl_lockexcl(&op->nfso_own->nfsow_rwlock, NFSCLSTATEMUTEXPTR);
 	NFSUNLOCKCLSTATE();
 	do {
 		error = nfscl_tryclose(op, tcred, nmp, p, loop_on_delayed);
 		if (error == NFSERR_GRACE)
 			(void) nfs_catnap(PZERO, error, "nfs_close");
 	} while (error == NFSERR_GRACE);
 	NFSLOCKCLSTATE();
 	nfscl_lockunlock(&op->nfso_own->nfsow_rwlock);
 
 	LIST_FOREACH_SAFE(lp, &op->nfso_lock, nfsl_list, nlp)
 		nfscl_freelockowner(lp, 0);
 	if (freeop && error != NFSERR_DELAY)
 		nfscl_freeopen(op, 0, true);
 	NFSUNLOCKCLSTATE();
 	NFSFREECRED(tcred);
 	return (error);
 }
 
 /*
  * The actual Close RPC.
  */
 int
 nfsrpc_closerpc(struct nfsrv_descript *nd, struct nfsmount *nmp,
     struct nfsclopen *op, struct ucred *cred, NFSPROC_T *p,
     int syscred)
 {
 	u_int32_t *tl;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_CLOSE, nmp, op->nfso_fh,
 	    op->nfso_fhlen, NULL, NULL, 0, 0, cred);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
 	if (NFSHASNFSV4N(nmp)) {
 		*tl++ = 0;
 		*tl++ = 0;
 	} else {
 		*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 		*tl++ = op->nfso_stateid.seqid;
 	}
 	*tl++ = op->nfso_stateid.other[0];
 	*tl++ = op->nfso_stateid.other[1];
 	*tl = op->nfso_stateid.other[2];
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	if (!NFSHASNFSV4N(nmp))
 		NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
 	if (nd->nd_repstat == 0)
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 	error = nd->nd_repstat;
 	if (!NFSHASNFSV4N(nmp) && error == NFSERR_STALESTATEID)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * V4 Open Confirm RPC.
  */
 int
 nfsrpc_openconfirm(vnode_t vp, u_int8_t *nfhp, int fhlen,
     struct nfsclopen *op, struct ucred *cred, NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	int error;
 
 	nmp = VFSTONFS(vp->v_mount);
 	if (NFSHASNFSV4N(nmp))
 		return (0);		/* No confirmation for NFSv4.1. */
 	nfscl_reqstart(nd, NFSPROC_OPENCONFIRM, nmp, nfhp, fhlen, NULL, NULL,
 	    0, 0, NULL);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
 	*tl++ = op->nfso_stateid.seqid;
 	*tl++ = op->nfso_stateid.other[0];
 	*tl++ = op->nfso_stateid.other[1];
 	*tl++ = op->nfso_stateid.other[2];
 	*tl = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
 	if (!nd->nd_repstat) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 		op->nfso_stateid.seqid = *tl++;
 		op->nfso_stateid.other[0] = *tl++;
 		op->nfso_stateid.other[1] = *tl++;
 		op->nfso_stateid.other[2] = *tl;
 	}
 	error = nd->nd_repstat;
 	if (error == NFSERR_STALESTATEID)
 		nfscl_initiate_recovery(op->nfso_own->nfsow_clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the setclientid and setclientid confirm RPCs. Called from nfs_statfs()
  * when a mount has just occurred and when the server replies NFSERR_EXPIRED.
  */
 int
 nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
     bool *retokp, struct ucred *cred, NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	u_int8_t *cp = NULL, *cp2, addr[INET6_ADDRSTRLEN + 9];
 	u_short port;
 	int error, isinet6 = 0, callblen;
 	nfsquad_t confirm;
 	static u_int32_t rev = 0;
 	struct nfsclds *dsp, *odsp;
 	struct in6_addr a6;
 	struct nfsclsession *tsep;
 	struct rpc_reconupcall recon;
 	struct nfscl_reconarg *rcp;
 
 	if (nfsboottime.tv_sec == 0)
 		NFSSETBOOTTIME(nfsboottime);
 	if (NFSHASNFSV4N(nmp)) {
 		error = NFSERR_BADSESSION;
 		odsp = dsp = NULL;
 		if (retokp != NULL) {
 			NFSLOCKMNT(nmp);
 			odsp = TAILQ_FIRST(&nmp->nm_sess);
 			NFSUNLOCKMNT(nmp);
 		}
 		if (odsp != NULL) {
 			/*
 			 * When a session already exists, first try a
 			 * CreateSession with the extant ClientID.
 			 */
 			dsp = malloc(sizeof(struct nfsclds) +
 			    odsp->nfsclds_servownlen + 1, M_NFSCLDS,
 			    M_WAITOK | M_ZERO);
 			dsp->nfsclds_expire = NFSD_MONOSEC + clp->nfsc_renew;
 			dsp->nfsclds_servownlen = odsp->nfsclds_servownlen;
 			dsp->nfsclds_sess.nfsess_clientid =
 			    odsp->nfsclds_sess.nfsess_clientid;
 			dsp->nfsclds_sess.nfsess_sequenceid =
 			    odsp->nfsclds_sess.nfsess_sequenceid + 1;
 			dsp->nfsclds_flags = odsp->nfsclds_flags;
 			if (dsp->nfsclds_servownlen > 0)
 				memcpy(dsp->nfsclds_serverown,
 				    odsp->nfsclds_serverown,
 				    dsp->nfsclds_servownlen + 1);
 			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 			mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
 			    NULL, MTX_DEF);
 			nfscl_initsessionslots(&dsp->nfsclds_sess);
 			error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
 			    &nmp->nm_sockreq, NULL,
 			    dsp->nfsclds_sess.nfsess_sequenceid, 1, cred, p);
 			NFSCL_DEBUG(1, "create session for extant "
 			    "ClientID=%d\n", error);
 			if (error != 0) {
 				nfscl_freenfsclds(dsp);
 				dsp = NULL;
 				/*
 				 * If *retokp is true, return any error other
 				 * than NFSERR_STALECLIENTID,
 				 * NFSERR_BADSESSION or NFSERR_STALEDONTRECOVER
 				 * so that nfscl_recover() will not loop.
 				 */
 				if (*retokp)
 					return (NFSERR_IO);
 			} else
 				*retokp = true;
 		} else if (retokp != NULL && *retokp)
 			return (NFSERR_IO);
 		if (error != 0) {
 			/*
 			 * Either there was no previous session or the
 			 * CreateSession attempt failed, so...
 			 * do an ExchangeID followed by the CreateSession.
 			 */
 			clp->nfsc_rev = rev++;
 			error = nfsrpc_exchangeid(nmp, clp, &nmp->nm_sockreq, 0,
 			    NFSV4EXCH_USEPNFSMDS | NFSV4EXCH_USENONPNFS, &dsp,
 			    cred, p);
 			NFSCL_DEBUG(1, "aft exch=%d\n", error);
 			if (error == 0)
 				error = nfsrpc_createsession(nmp,
 				    &dsp->nfsclds_sess, &nmp->nm_sockreq, NULL,
 				    dsp->nfsclds_sess.nfsess_sequenceid, 1,
 				    cred, p);
 			NFSCL_DEBUG(1, "aft createsess=%d\n", error);
 		}
 		if (error == 0) {
 			/*
 			 * If the session supports a backchannel, set up
 			 * the BindConnectionToSession call in the krpc
 			 * so that it is done on a reconnection.
 			 */
 			if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0) {
 				rcp = mem_alloc(sizeof(*rcp));
 				rcp->minorvers = nmp->nm_minorvers;
 				memcpy(rcp->sessionid,
 				    dsp->nfsclds_sess.nfsess_sessionid,
 				    NFSX_V4SESSIONID);
 				recon.call = nfsrpc_bindconnsess;
 				recon.arg = rcp;
 				CLNT_CONTROL(nmp->nm_client, CLSET_RECONUPCALL,
 				    &recon);
 			}
 
 			NFSLOCKMNT(nmp);
 			/*
 			 * The old sessions cannot be safely free'd
 			 * here, since they may still be used by
 			 * in-progress RPCs.
 			 */
 			tsep = NULL;
 			if (TAILQ_FIRST(&nmp->nm_sess) != NULL) {
 				/*
 				 * Mark the old session defunct.  Needed
 				 * when called from nfscl_hasexpired().
 				 */
 				tsep = NFSMNT_MDSSESSION(nmp);
 				tsep->nfsess_defunct = 1;
 			}
 			TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp,
 			    nfsclds_list);
 			/*
 			 * Wake up RPCs waiting for a slot on the
 			 * old session. These will then fail with
 			 * NFSERR_BADSESSION and be retried with the
 			 * new session by nfsv4_setsequence().
 			 * Also wakeup() processes waiting for the
 			 * new session.
 			 */
 			if (tsep != NULL)
 				wakeup(&tsep->nfsess_slots);
 			wakeup(&nmp->nm_sess);
 			NFSUNLOCKMNT(nmp);
 		} else if (dsp != NULL)
 			nfscl_freenfsclds(dsp);
 		if (error == 0 && reclaim == 0) {
 			error = nfsrpc_reclaimcomplete(nmp, cred, p);
 			NFSCL_DEBUG(1, "aft reclaimcomp=%d\n", error);
 			if (error == NFSERR_COMPLETEALREADY ||
 			    error == NFSERR_NOTSUPP)
 				/* Ignore this error. */
 				error = 0;
 		}
 		return (error);
 	} else if (retokp != NULL && *retokp)
 		return (NFSERR_IO);
 	clp->nfsc_rev = rev++;
 
 	/*
 	 * Allocate a single session structure for NFSv4.0, because some of
 	 * the fields are used by NFSv4.0 although it doesn't do a session.
 	 */
 	dsp = malloc(sizeof(struct nfsclds), M_NFSCLDS, M_WAITOK | M_ZERO);
 	mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 	mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession", NULL, MTX_DEF);
 	NFSLOCKMNT(nmp);
 	TAILQ_INSERT_HEAD(&nmp->nm_sess, dsp, nfsclds_list);
 	tsep = NFSMNT_MDSSESSION(nmp);
 	NFSUNLOCKMNT(nmp);
 
 	nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL, 0, 0,
 	    NULL);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec);
 	*tl = txdr_unsigned(clp->nfsc_rev);
 	(void) nfsm_strtom(nd, clp->nfsc_id, clp->nfsc_idlen);
 
 	/*
 	 * set up the callback address
 	 */
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFS_CALLBCKPROG);
 	callblen = strlen(nfsv4_callbackaddr);
 	if (callblen == 0)
 		cp = nfscl_getmyip(nmp, &a6, &isinet6);
 	if (nfscl_enablecallb && nfs_numnfscbd > 0 &&
 	    (callblen > 0 || cp != NULL)) {
 		port = htons(nfsv4_cbport);
 		cp2 = (u_int8_t *)&port;
 #ifdef INET6
 		if ((callblen > 0 &&
 		     strchr(nfsv4_callbackaddr, ':')) || isinet6) {
 			char ip6buf[INET6_ADDRSTRLEN], *ip6add;
 
 			(void) nfsm_strtom(nd, "tcp6", 4);
 			if (callblen == 0) {
 				ip6_sprintf(ip6buf, (struct in6_addr *)cp);
 				ip6add = ip6buf;
 			} else {
 				ip6add = nfsv4_callbackaddr;
 			}
 			snprintf(addr, INET6_ADDRSTRLEN + 9, "%s.%d.%d",
 			    ip6add, cp2[0], cp2[1]);
 		} else
 #endif
 		{
 			(void) nfsm_strtom(nd, "tcp", 3);
 			if (callblen == 0)
 				snprintf(addr, INET6_ADDRSTRLEN + 9,
 				    "%d.%d.%d.%d.%d.%d", cp[0], cp[1],
 				    cp[2], cp[3], cp2[0], cp2[1]);
 			else
 				snprintf(addr, INET6_ADDRSTRLEN + 9,
 				    "%s.%d.%d", nfsv4_callbackaddr,
 				    cp2[0], cp2[1]);
 		}
 		(void) nfsm_strtom(nd, addr, strlen(addr));
 	} else {
 		(void) nfsm_strtom(nd, "tcp", 3);
 		(void) nfsm_strtom(nd, "0.0.0.0.0.0", 11);
 	}
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(clp->nfsc_cbident);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 		NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 	    NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 	    tsep->nfsess_clientid.lval[0] = *tl++;
 	    tsep->nfsess_clientid.lval[1] = *tl++;
 	    confirm.lval[0] = *tl++;
 	    confirm.lval[1] = *tl;
 	    m_freem(nd->nd_mrep);
 	    nd->nd_mrep = NULL;
 
 	    /*
 	     * and confirm it.
 	     */
 	    nfscl_reqstart(nd, NFSPROC_SETCLIENTIDCFRM, nmp, NULL, 0, NULL,
 		NULL, 0, 0, NULL);
 	    NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 	    *tl++ = tsep->nfsess_clientid.lval[0];
 	    *tl++ = tsep->nfsess_clientid.lval[1];
 	    *tl++ = confirm.lval[0];
 	    *tl = confirm.lval[1];
 	    nd->nd_flag |= ND_USEGSSNAME;
 	    error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p,
 		cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	    if (error)
 		return (error);
 	    m_freem(nd->nd_mrep);
 	    nd->nd_mrep = NULL;
 	}
 	error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs getattr call.
  */
 int
 nfsrpc_getattr(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
     struct nfsvattr *nap)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 	nfsattrbit_t attrbits;
 	struct nfsnode *np;
 	struct nfsmount *nmp;
 
 	nmp = VFSTONFS(vp->v_mount);
 	np = VTONFS(vp);
 	if ((nmp->nm_privflag & NFSMNTP_FAKEROOTFH) != 0 &&
 	    nmp->nm_fhsize == 0) {
 		/* Attempt to get the actual root file handle. */
 		error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp), cred, p);
 		if (error != 0)
 			return (EACCES);
 		if (np->n_fhp->nfh_len == NFSX_FHMAX + 1)
 			nfscl_statfs(vp, cred, p);
 	}
 	NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSGETATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (!nd->nd_repstat)
 		error = nfsm_loadattr(nd, nap);
 	else
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs getattr call with non-vnode arguments.
  */
 int
 nfsrpc_getattrnovp(struct nfsmount *nmp, u_int8_t *fhp, int fhlen, int syscred,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, u_int64_t *xidp,
     uint32_t *leasep)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error, vers = NFS_VER2;
 	nfsattrbit_t attrbits;
 
 	nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, fhp, fhlen, NULL, NULL, 0, 0,
 	    cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		vers = NFS_VER4;
 		NFSGETATTR_ATTRBIT(&attrbits);
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_LEASETIME);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	} else if (nd->nd_flag & ND_NFSV3) {
 		vers = NFS_VER3;
 	}
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, vers, NULL, 1, xidp, NULL);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		if ((nd->nd_flag & ND_NFSV4) != 0)
 			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 			    NULL, NULL, NULL, NULL, NULL, 0, NULL, leasep, NULL,
 			    NULL, NULL);
 		else
 			error = nfsm_loadattr(nd, nap);
 	} else
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do an nfs setattr operation.
  */
 int
 nfsrpc_setattr(vnode_t vp, struct vattr *vap, NFSACL_T *aclp,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *rnap, int *attrflagp)
 {
 	int error, expireret = 0, openerr, retrycnt;
 	u_int32_t clidrev = 0, mode;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsfh *nfhp;
 	nfsv4stateid_t stateid;
 	void *lckp;
 
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	if (vap != NULL && NFSATTRISSET(u_quad_t, vap, va_size))
 		mode = NFSV4OPEN_ACCESSWRITE;
 	else
 		mode = NFSV4OPEN_ACCESSREAD;
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		openerr = 1;
 		if (NFSHASNFSV4(nmp)) {
 			nfhp = VTONFS(vp)->n_fhp;
 			error = nfscl_getstateid(vp, nfhp->nfh_fh,
 			    nfhp->nfh_len, mode, 0, cred, p, &stateid, &lckp);
 			if (error && vp->v_type == VREG &&
 			    (mode == NFSV4OPEN_ACCESSWRITE ||
 			     nfstest_openallsetattr)) {
 				/*
 				 * No Open stateid, so try and open the file
 				 * now.
 				 */
 				if (mode == NFSV4OPEN_ACCESSWRITE)
 					openerr = nfsrpc_open(vp, FWRITE, cred,
 					    p);
 				else
 					openerr = nfsrpc_open(vp, FREAD, cred,
 					    p);
 				if (!openerr)
 					(void) nfscl_getstateid(vp,
 					    nfhp->nfh_fh, nfhp->nfh_len,
 					    mode, 0, cred, p, &stateid, &lckp);
 			}
 		}
 		if (vap != NULL)
 			error = nfsrpc_setattrrpc(vp, vap, &stateid, cred, p,
 			    rnap, attrflagp);
 		else
 			error = nfsrpc_setaclrpc(vp, cred, p, aclp, &stateid);
 		if (error == NFSERR_OPENMODE && mode == NFSV4OPEN_ACCESSREAD) {
 			NFSLOCKMNT(nmp);
 			nmp->nm_state |= NFSSTA_OPENMODE;
 			NFSUNLOCKMNT(nmp);
 		}
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (!openerr)
 			(void) nfsrpc_close(vp, 0, p);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_setattr");
 		} else if ((error == NFSERR_EXPIRED ||
 		    ((!NFSHASINT(nmp) || !NFSHASNFSV4N(nmp)) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp) &&
 		    NFSHASNFSV4N(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4) ||
 	    (error == NFSERR_OPENMODE && mode == NFSV4OPEN_ACCESSREAD &&
 	     retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 static int
 nfsrpc_setattrrpc(vnode_t vp, struct vattr *vap,
     nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
     struct nfsvattr *rnap, int *attrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_SETATTR, vp, cred);
 	if (nd->nd_flag & ND_NFSV4)
 		nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 	vap->va_type = vp->v_type;
 	nfscl_fillsattr(nd, vap, vp, NFSSATTR_FULL, 0);
 	if (nd->nd_flag & ND_NFSV3) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = newnfs_false;
 	} else if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSGETATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 		error = nfscl_wcc_data(nd, vp, rnap, attrflagp, NULL, NULL);
 	if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4 && !error)
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 	if (!(nd->nd_flag & ND_NFSV3) && !nd->nd_repstat && !error)
 		error = nfscl_postop_attr(nd, rnap, attrflagp);
 	m_freem(nd->nd_mrep);
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	return (error);
 }
 
 /*
  * nfs lookup rpc
  */
 int
 nfsrpc_lookup(vnode_t dvp, char *name, int len, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *dnap, struct nfsvattr *nap,
     struct nfsfh **nfhpp, int *attrflagp, int *dattrflagp, uint32_t openmode)
 {
 	uint32_t deleg, rflags, *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	struct nfsnode *np;
 	struct nfsfh *nfhp;
 	nfsattrbit_t attrbits;
 	int error = 0, lookupp = 0, newone, ret, retop;
 	uint8_t own[NFSV4CL_LOCKNAMELEN];
 	struct nfsclopen *op;
 	struct nfscldeleg *ndp;
 	nfsv4stateid_t stateid;
 
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (dvp->v_type != VDIR)
 		return (ENOTDIR);
 	nmp = VFSTONFS(dvp->v_mount);
 	if (len > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	if (NFSHASNFSV4(nmp) && len == 1 &&
 		name[0] == '.') {
 		/*
 		 * Just return the current dir's fh.
 		 */
 		np = VTONFS(dvp);
 		nfhp = malloc(sizeof (struct nfsfh) +
 			np->n_fhp->nfh_len, M_NFSFH, M_WAITOK);
 		nfhp->nfh_len = np->n_fhp->nfh_len;
 		NFSBCOPY(np->n_fhp->nfh_fh, nfhp->nfh_fh, nfhp->nfh_len);
 		*nfhpp = nfhp;
 		return (0);
 	}
 	if (NFSHASNFSV4(nmp) && len == 2 &&
 		name[0] == '.' && name[1] == '.') {
 		lookupp = 1;
 		openmode = 0;
 		NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, dvp, cred);
 	} else if (openmode != 0) {
 		NFSCL_REQSTART(nd, NFSPROC_LOOKUPOPEN, dvp, cred);
 		nfsm_strtom(nd, name, len);
 	} else {
 		NFSCL_REQSTART(nd, NFSPROC_LOOKUP, dvp, cred);
 		(void) nfsm_strtom(nd, name, len);
 	}
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSGETATTR_ATTRBIT(&attrbits);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		if (openmode != 0) {
 			/* Test for a VREG file. */
 			NFSZERO_ATTRBIT(&attrbits);
 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TYPE);
 			NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_VERIFY);
 			nfsrv_putattrbit(nd, &attrbits);
 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			*tl++ = txdr_unsigned(NFSX_UNSIGNED);
 			*tl = vtonfsv34_type(VREG);
 
 			/* Attempt the Open for VREG. */
 			nfscl_filllockowner(NULL, own, F_POSIX);
 			NFSM_BUILD(tl, uint32_t *, 6 * NFSX_UNSIGNED);
 			*tl++ = txdr_unsigned(NFSV4OP_OPEN);
 			*tl++ = 0;		/* seqid, ignored. */
 			*tl++ = txdr_unsigned(openmode);
 			*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
 			*tl++ = 0;		/* ClientID, ignored. */
 			*tl = 0;
 			nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN);
 			NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
 			*tl = txdr_unsigned(NFSV4OPEN_CLAIMFH);
 		}
 	}
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	ndp = NULL;
 	if (nd->nd_repstat) {
 		/*
 		 * When an NFSv4 Lookupp returns ENOENT, it means that
 		 * the lookup is at the root of an fs, so return this dir.
 		 */
 		if (nd->nd_repstat == NFSERR_NOENT && lookupp) {
 		    np = VTONFS(dvp);
 		    nfhp = malloc(sizeof (struct nfsfh) +
 			np->n_fhp->nfh_len, M_NFSFH, M_WAITOK);
 		    nfhp->nfh_len = np->n_fhp->nfh_len;
 		    NFSBCOPY(np->n_fhp->nfh_fh, nfhp->nfh_fh, nfhp->nfh_len);
 		    *nfhpp = nfhp;
 		    m_freem(nd->nd_mrep);
 		    return (0);
 		}
 		if (nd->nd_flag & ND_NFSV3)
 		    error = nfscl_postop_attr(nd, dnap, dattrflagp);
 		else if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 		    ND_NFSV4) {
 			/* Load the directory attributes. */
 			error = nfsm_loadattr(nd, dnap);
 			if (error != 0)
 				goto nfsmout;
 			*dattrflagp = 1;
 		}
 		/* Check Lookup operation reply status. */
 		if (openmode != 0 && (nd->nd_flag & ND_NOMOREDATA) == 0) {
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			if (*++tl != 0)
 				goto nfsmout;
 		}
 		/* Look for GetFH reply. */
 		if (openmode != 0 && (nd->nd_flag & ND_NOMOREDATA) == 0) {
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			if (*++tl != 0)
 				goto nfsmout;
 			error = nfsm_getfh(nd, nfhpp);
 			if (error)
 				goto nfsmout;
 		}
 		/* Look for Getattr reply. */
 		if (openmode != 0 && (nd->nd_flag & ND_NOMOREDATA) == 0) {
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			if (*++tl != 0)
 				goto nfsmout;
 			error = nfsm_loadattr(nd, nap);
 			if (error == 0) {
 				/*
 				 * We have now successfully completed the
 				 * lookup, so set nd_repstat to 0.
 				 */
 				nd->nd_repstat = 0;
 				*attrflagp = 1;
 			}
 		}
 		goto nfsmout;
 	}
 	if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 		/* Load the directory attributes. */
 		error = nfsm_loadattr(nd, dnap);
 		if (error != 0)
 			goto nfsmout;
 		*dattrflagp = 1;
 		/* Skip over the Lookup and GetFH operation status values. */
 		NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 	}
 	error = nfsm_getfh(nd, nfhpp);
 	if (error)
 		goto nfsmout;
 
 	error = nfscl_postop_attr(nd, nap, attrflagp);
 	if (openmode != 0 && error == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID +
 		    10 * NFSX_UNSIGNED);
 		tl += 4;	/* Skip over Verify+Open status. */
 		stateid.seqid = *tl++;
 		stateid.other[0] = *tl++;
 		stateid.other[1] = *tl++;
 		stateid.other[2] = *tl;
 		rflags = fxdr_unsigned(uint32_t, *(tl + 6));
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		if (error != 0)
 			goto nfsmout;
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		deleg = fxdr_unsigned(uint32_t, *tl);
 		if (deleg == NFSV4OPEN_DELEGATEREAD ||
 		    deleg == NFSV4OPEN_DELEGATEWRITE) {
 			/*
 			 * Just need to fill in the fields used by
 			 * nfscl_trydelegreturn().
 			 * Mark the mount point as acquiring
 			 * delegations, so NFSPROC_LOOKUPOPEN will
 			 * no longer be done.
 			 */
 			NFSLOCKMNT(nmp);
 			nmp->nm_privflag |= NFSMNTP_DELEGISSUED;
 			NFSUNLOCKMNT(nmp);
 			ndp = malloc(sizeof(struct nfscldeleg) +
 			    (*nfhpp)->nfh_len, M_NFSCLDELEG, M_WAITOK);
 			ndp->nfsdl_fhlen = (*nfhpp)->nfh_len;
 			NFSBCOPY((*nfhpp)->nfh_fh, ndp->nfsdl_fh,
 			    ndp->nfsdl_fhlen);
 			newnfs_copyincred(cred, &ndp->nfsdl_cred);
 			NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
 			ndp->nfsdl_stateid.seqid = *tl++;
 			ndp->nfsdl_stateid.other[0] = *tl++;
 			ndp->nfsdl_stateid.other[1] = *tl++;
 			ndp->nfsdl_stateid.other[2] = *tl++;
 		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		ret = nfscl_open(dvp, (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len,
 		    openmode, 0, cred, p, NULL, &op, &newone, &retop, 1, true);
 		if (ret != 0)
 			goto nfsmout;
 		if (newone != 0) {
 			op->nfso_stateid.seqid = stateid.seqid;
 			op->nfso_stateid.other[0] = stateid.other[0];
 			op->nfso_stateid.other[1] = stateid.other[1];
 			op->nfso_stateid.other[2] = stateid.other[2];
 			op->nfso_mode = openmode;
 		} else {
 			op->nfso_stateid.seqid = stateid.seqid;
 			if (retop == NFSCLOPEN_DOOPEN)
 				op->nfso_mode |= openmode;
 		}
 		if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) != 0 ||
 		    nfscl_assumeposixlocks)
 			op->nfso_posixlock = 1;
 		else
 			op->nfso_posixlock = 0;
 		nfscl_openrelease(nmp, op, 0, 0);
 		if (ndp != NULL) {
 			/*
 			 * Since we do not have the vnode, we
 			 * cannot invalidate cached attributes.
 			 * Just return the delegation.
 			 */
 			nfscl_trydelegreturn(ndp, cred, nmp, p);
 		}
 	}
 	if ((nd->nd_flag & ND_NFSV3) && !error)
 		error = nfscl_postop_attr(nd, dnap, dattrflagp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	if (!error && nd->nd_repstat)
 		error = nd->nd_repstat;
 	free(ndp, M_NFSCLDELEG);
 	return (error);
 }
 
 /*
  * Do a readlink rpc.
  */
 int
 nfsrpc_readlink(vnode_t vp, struct uio *uiop, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsnode *np = VTONFS(vp);
 	nfsattrbit_t attrbits;
 	int error, len, cangetattr = 1;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_READLINK, vp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		/*
 		 * And do a Getattr op.
 		 */
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSGETATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV3)
 		error = nfscl_postop_attr(nd, nap, attrflagp);
 	if (!nd->nd_repstat && !error) {
 		NFSM_STRSIZ(len, NFS_MAXPATHLEN);
 		/*
 		 * This seems weird to me, but must have been added to
 		 * FreeBSD for some reason. The only thing I can think of
 		 * is that there was/is some server that replies with
 		 * more link data than it should?
 		 */
 		if (len == NFS_MAXPATHLEN) {
 			NFSLOCKNODE(np);
 			if (np->n_size > 0 && np->n_size < NFS_MAXPATHLEN) {
 				len = np->n_size;
 				cangetattr = 0;
 			}
 			NFSUNLOCKNODE(np);
 		}
 		error = nfsm_mbufuio(nd, uiop, len);
 		if ((nd->nd_flag & ND_NFSV4) && !error && cangetattr)
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 	}
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Read operation.
  */
 int
 nfsrpc_read(vnode_t vp, struct uio *uiop, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	int error, expireret = 0, retrycnt;
 	u_int32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *np = VTONFS(vp);
 	struct ucred *newcred;
 	struct nfsfh *nfhp = NULL;
 	nfsv4stateid_t stateid;
 	void *lckp;
 
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	newcred = cred;
 	if (NFSHASNFSV4(nmp)) {
 		nfhp = np->n_fhp;
 		newcred = NFSNEWCRED(cred);
 	}
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		if (NFSHASNFSV4(nmp))
 			(void)nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 			    NFSV4OPEN_ACCESSREAD, 0, newcred, p, &stateid,
 			    &lckp);
 		error = nfsrpc_readrpc(vp, uiop, newcred, &stateid, p, nap,
 		    attrflagp);
 		if (error == NFSERR_OPENMODE) {
 			NFSLOCKMNT(nmp);
 			nmp->nm_state |= NFSSTA_OPENMODE;
 			NFSUNLOCKMNT(nmp);
 		}
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_read");
 		} else if ((error == NFSERR_EXPIRED ||
 		    ((!NFSHASINT(nmp) || !NFSHASNFSV4N(nmp)) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp) &&
 		    NFSHASNFSV4N(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4) ||
 	    (error == NFSERR_OPENMODE && retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	if (NFSHASNFSV4(nmp))
 		NFSFREECRED(newcred);
 	return (error);
 }
 
 /*
  * The actual read RPC.
  */
 static int
 nfsrpc_readrpc(vnode_t vp, struct uio *uiop, struct ucred *cred,
     nfsv4stateid_t *stateidp, NFSPROC_T *p, struct nfsvattr *nap,
     int *attrflagp)
 {
 	u_int32_t *tl;
 	int error = 0, len, retlen, tsiz, eof = 0;
 	struct nfsrv_descript nfsd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsrv_descript *nd = &nfsd;
 	int rsize;
 	off_t tmp_off;
 
 	*attrflagp = 0;
 	tsiz = uiop->uio_resid;
 	tmp_off = uiop->uio_offset + tsiz;
 	NFSLOCKMNT(nmp);
 	if (tmp_off > nmp->nm_maxfilesize || tmp_off < uiop->uio_offset) {
 		NFSUNLOCKMNT(nmp);
 		return (EFBIG);
 	}
 	rsize = nmp->nm_rsize;
 	NFSUNLOCKMNT(nmp);
 	nd->nd_mrep = NULL;
 	while (tsiz > 0) {
 		*attrflagp = 0;
 		len = (tsiz > rsize) ? rsize : tsiz;
 		NFSCL_REQSTART(nd, NFSPROC_READ, vp, cred);
 		if (nd->nd_flag & ND_NFSV4)
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED * 3);
 		if (nd->nd_flag & ND_NFSV2) {
 			*tl++ = txdr_unsigned(uiop->uio_offset);
 			*tl++ = txdr_unsigned(len);
 			*tl = 0;
 		} else {
 			txdr_hyper(uiop->uio_offset, tl);
 			*(tl + 2) = txdr_unsigned(len);
 		}
 		/*
 		 * Since I can't do a Getattr for NFSv4 for Write, there
 		 * doesn't seem any point in doing one here, either.
 		 * (See the comment in nfsrpc_writerpc() for more info.)
 		 */
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (nd->nd_flag & ND_NFSV3) {
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 		} else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
 			error = nfsm_loadattr(nd, nap);
 			if (!error)
 				*attrflagp = 1;
 		}
 		if (nd->nd_repstat || error) {
 			if (!error)
 				error = nd->nd_repstat;
 			goto nfsmout;
 		}
 		if (nd->nd_flag & ND_NFSV3) {
 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			eof = fxdr_unsigned(int, *(tl + 1));
 		} else if (nd->nd_flag & ND_NFSV4) {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			eof = fxdr_unsigned(int, *tl);
 		}
 		NFSM_STRSIZ(retlen, len);
 		error = nfsm_mbufuio(nd, uiop, retlen);
 		if (error)
 			goto nfsmout;
 		m_freem(nd->nd_mrep);
 		nd->nd_mrep = NULL;
 		tsiz -= retlen;
 		if (!(nd->nd_flag & ND_NFSV2)) {
 			if (eof || retlen == 0)
 				tsiz = 0;
 		} else if (retlen < len)
 			tsiz = 0;
 	}
 	return (0);
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs write operation
  * When called_from_strategy != 0, it should return EIO for an error that
  * indicates recovery is in progress, so that the buffer will be left
  * dirty and be written back to the server later. If it loops around,
  * the recovery thread could get stuck waiting for the buffer and recovery
  * will then deadlock.
  */
 int
 nfsrpc_write(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
     int called_from_strategy, int ioflag)
 {
 	int error, expireret = 0, retrycnt, nostateid;
 	u_int32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *np = VTONFS(vp);
 	struct ucred *newcred;
 	struct nfsfh *nfhp = NULL;
 	nfsv4stateid_t stateid;
 	void *lckp;
 
 	KASSERT(*must_commit >= 0 && *must_commit <= 2,
 	    ("nfsrpc_write: must_commit out of range=%d", *must_commit));
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	newcred = cred;
 	if (NFSHASNFSV4(nmp)) {
 		newcred = NFSNEWCRED(cred);
 		nfhp = np->n_fhp;
 	}
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		nostateid = 0;
 		if (NFSHASNFSV4(nmp)) {
 			(void)nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 			    NFSV4OPEN_ACCESSWRITE, 0, newcred, p, &stateid,
 			    &lckp);
 			if (stateid.other[0] == 0 && stateid.other[1] == 0 &&
 			    stateid.other[2] == 0) {
 				nostateid = 1;
 				NFSCL_DEBUG(1, "stateid0 in write\n");
 			}
 		}
 
 		/*
 		 * If there is no stateid for NFSv4, it means this is an
 		 * extraneous write after close. Basically a poorly
 		 * implemented buffer cache. Just don't do the write.
 		 */
 		if (nostateid)
 			error = 0;
 		else
 			error = nfsrpc_writerpc(vp, uiop, iomode, must_commit,
 			    newcred, &stateid, p, nap, attrflagp, ioflag);
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_write");
 		} else if ((error == NFSERR_EXPIRED ||
 		    ((!NFSHASINT(nmp) || !NFSHASNFSV4N(nmp)) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp) &&
 		    NFSHASNFSV4N(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_DELAY ||
 	    ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER) && called_from_strategy == 0) ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error != 0 && (retrycnt >= 4 ||
 	    ((error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER) && called_from_strategy != 0)))
 		error = EIO;
 	if (NFSHASNFSV4(nmp))
 		NFSFREECRED(newcred);
 	return (error);
 }
 
 /*
  * The actual write RPC.
  */
 static int
 nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
     int *must_commit, struct ucred *cred, nfsv4stateid_t *stateidp,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp, int ioflag)
 {
 	u_int32_t *tl;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *np = VTONFS(vp);
 	int error = 0, len, rlen, commit, committed = NFSWRITE_FILESYNC;
 	int wccflag = 0;
 	int32_t backup;
 	struct nfsrv_descript *nd;
 	nfsattrbit_t attrbits;
 	uint64_t tmp_off;
 	ssize_t tsiz, wsize;
 	bool do_append;
 
 	KASSERT(uiop->uio_iovcnt == 1, ("nfs: writerpc iovcnt > 1"));
 	*attrflagp = 0;
 	tsiz = uiop->uio_resid;
 	tmp_off = uiop->uio_offset + tsiz;
 	NFSLOCKMNT(nmp);
 	if (tmp_off > nmp->nm_maxfilesize || tmp_off < uiop->uio_offset) {
 		NFSUNLOCKMNT(nmp);
 		return (EFBIG);
 	}
 	wsize = nmp->nm_wsize;
 	do_append = false;
 	if ((ioflag & IO_APPEND) != 0 && NFSHASNFSV4(nmp) && !NFSHASPNFS(nmp))
 		do_append = true;
 	NFSUNLOCKMNT(nmp);
 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK);
 	nd->nd_mrep = NULL;	/* NFSv2 sometimes does a write with */
 	nd->nd_repstat = 0;	/* uio_resid == 0, so the while is not done */
 	while (tsiz > 0) {
 		*attrflagp = 0;
 		len = (tsiz > wsize) ? wsize : tsiz;
 		if (do_append)
 			NFSCL_REQSTART(nd, NFSPROC_APPENDWRITE, vp, cred);
 		else
 			NFSCL_REQSTART(nd, NFSPROC_WRITE, vp, cred);
 		if (nd->nd_flag & ND_NFSV4) {
 			if (do_append) {
 				NFSZERO_ATTRBIT(&attrbits);
 				NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
 				nfsrv_putattrbit(nd, &attrbits);
 				NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED +
 				    NFSX_HYPER);
 				*tl++ = txdr_unsigned(NFSX_HYPER);
 				txdr_hyper(uiop->uio_offset, tl); tl += 2;
 				*tl = txdr_unsigned(NFSV4OP_WRITE);
 			}
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER+2*NFSX_UNSIGNED);
 			txdr_hyper(uiop->uio_offset, tl);
 			tl += 2;
 			*tl++ = txdr_unsigned(*iomode);
 			*tl = txdr_unsigned(len);
 		} else if (nd->nd_flag & ND_NFSV3) {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER+3*NFSX_UNSIGNED);
 			txdr_hyper(uiop->uio_offset, tl);
 			tl += 2;
 			*tl++ = txdr_unsigned(len);
 			*tl++ = txdr_unsigned(*iomode);
 			*tl = txdr_unsigned(len);
 		} else {
 			u_int32_t x;
 
 			NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 			/*
 			 * Not sure why someone changed this, since the
 			 * RFC clearly states that "beginoffset" and
 			 * "totalcount" are ignored, but it wouldn't
 			 * surprise me if there's a busted server out there.
 			 */
 			/* Set both "begin" and "current" to non-garbage. */
 			x = txdr_unsigned((u_int32_t)uiop->uio_offset);
 			*tl++ = x;      /* "begin offset" */
 			*tl++ = x;      /* "current offset" */
 			x = txdr_unsigned(len);
 			*tl++ = x;      /* total to this offset */
 			*tl = x;        /* size of this write */
 		}
 		nfsm_uiombuf(nd, uiop, len);
 		/*
 		 * Although it is tempting to do a normal Getattr Op in the
 		 * NFSv4 compound, the result can be a nearly hung client
 		 * system if the Getattr asks for Owner and/or OwnerGroup.
 		 * It occurs when the client can't map either the Owner or
 		 * Owner_group name in the Getattr reply to a uid/gid. When
 		 * there is a cache miss, the kernel does an upcall to the
 		 * nfsuserd. Then, it can try and read the local /etc/passwd
 		 * or /etc/group file. It can then block in getnewbuf(),
 		 * waiting for dirty writes to be pushed to the NFS server.
 		 * The only reason this doesn't result in a complete
 		 * deadlock, is that the upcall times out and allows
 		 * the write to complete. However, progress is so slow
 		 * that it might just as well be deadlocked.
 		 * As such, we get the rest of the attributes, but not
 		 * Owner or Owner_group.
 		 * nb: nfscl_loadattrcache() needs to be told that these
 		 *     partial attributes from a write rpc are being
 		 *     passed in, via a argument flag.
 		 */
 		if (nd->nd_flag & ND_NFSV4) {
 			NFSWRITEGETATTR_ATTRBIT(&attrbits);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_GETATTR);
 			(void) nfsrv_putattrbit(nd, &attrbits);
 		}
 		error = nfscl_request(nd, vp, p, cred);
 		if (error) {
 			free(nd, M_TEMP);
 			return (error);
 		}
 		if (nd->nd_repstat) {
 			/*
 			 * In case the rpc gets retried, roll
 			 * the uio fields changed by nfsm_uiombuf()
 			 * back.
 			 */
 			uiop->uio_offset -= len;
 			uiop->uio_resid += len;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base - len;
 			uiop->uio_iov->iov_len += len;
 		}
 		if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 			error = nfscl_wcc_data(nd, vp, nap, attrflagp,
 			    &wccflag, &tmp_off);
 			if (error)
 				goto nfsmout;
 		}
 		if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 		    (ND_NFSV4 | ND_NOMOREDATA) &&
 		    nd->nd_repstat == NFSERR_NOTSAME && do_append) {
 			/*
 			 * Verify of the file's size failed, so redo the
 			 * write using the file's size as returned in
 			 * the wcc attributes.
 			 */
 			if (tmp_off + tsiz <= nmp->nm_maxfilesize) {
 				do_append = false;
 				uiop->uio_offset = tmp_off;
 				m_freem(nd->nd_mrep);
 				nd->nd_mrep = NULL;
 				continue;
 			} else
 				nd->nd_repstat = EFBIG;
 		}
 		if (!nd->nd_repstat) {
 			if (do_append) {
 				/* Strip off the Write reply status. */
 				do_append = false;
 				NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			}
 			if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 				NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED
 					+ NFSX_VERF);
 				rlen = fxdr_unsigned(int, *tl++);
 				if (rlen == 0) {
 					error = NFSERR_IO;
 					goto nfsmout;
 				} else if (rlen < len) {
 					backup = len - rlen;
 					uiop->uio_iov->iov_base =
 					    (char *)uiop->uio_iov->iov_base -
 					    backup;
 					uiop->uio_iov->iov_len += backup;
 					uiop->uio_offset -= backup;
 					uiop->uio_resid += backup;
 					len = rlen;
 				}
 				commit = fxdr_unsigned(int, *tl++);
 
 				/*
 				 * Return the lowest commitment level
 				 * obtained by any of the RPCs.
 				 */
 				if (committed == NFSWRITE_FILESYNC)
 					committed = commit;
 				else if (committed == NFSWRITE_DATASYNC &&
 					commit == NFSWRITE_UNSTABLE)
 					committed = commit;
 				NFSLOCKMNT(nmp);
 				if (!NFSHASWRITEVERF(nmp)) {
 					NFSBCOPY((caddr_t)tl,
 					    (caddr_t)&nmp->nm_verf[0],
 					    NFSX_VERF);
 					NFSSETWRITEVERF(nmp);
 	    			} else if (NFSBCMP(tl, nmp->nm_verf,
 				    NFSX_VERF) && *must_commit != 2) {
 					*must_commit = 1;
 					NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 				}
 				NFSUNLOCKMNT(nmp);
 			}
 			if (nd->nd_flag & ND_NFSV4)
 				NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			if (nd->nd_flag & (ND_NFSV2 | ND_NFSV4)) {
 				error = nfsm_loadattr(nd, nap);
 				if (!error)
 					*attrflagp = NFS_LATTR_NOSHRINK;
 			}
 		} else {
 			error = nd->nd_repstat;
 		}
 		if (error)
 			goto nfsmout;
 		NFSWRITERPC_SETTIME(wccflag, np, nap, (nd->nd_flag & ND_NFSV4));
 		m_freem(nd->nd_mrep);
 		nd->nd_mrep = NULL;
 		tsiz -= len;
 	}
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	*iomode = committed;
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	free(nd, M_TEMP);
 	return (error);
 }
 
 /*
  * Do an nfs deallocate operation.
  */
 int
 nfsrpc_deallocate(vnode_t vp, off_t offs, off_t len, struct nfsvattr *nap,
     int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	int error, expireret = 0, openerr, retrycnt;
 	uint32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsfh *nfhp;
 	nfsv4stateid_t stateid;
 	void *lckp;
 
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		openerr = 1;
 		nfhp = VTONFS(vp)->n_fhp;
 		error = nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 		    NFSV4OPEN_ACCESSWRITE, 0, cred, p, &stateid, &lckp);
 		if (error != 0) {
 			/*
 			 * No Open stateid, so try and open the file
 			 * now.
 			 */
 			openerr = nfsrpc_open(vp, FWRITE, cred, p);
 			if (openerr == 0)
 				nfscl_getstateid(vp, nfhp->nfh_fh,
 				    nfhp->nfh_len, NFSV4OPEN_ACCESSWRITE, 0,
 				    cred, p, &stateid, &lckp);
 		}
 		error = nfsrpc_deallocaterpc(vp, offs, len, &stateid, nap,
 		    attrflagp, cred, p);
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (openerr == 0)
 			nfsrpc_close(vp, 0, p);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_deallocate");
 		} else if ((error == NFSERR_EXPIRED || (!NFSHASINT(nmp) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 /*
  * The actual deallocate RPC.
  */
 static int
 nfsrpc_deallocaterpc(vnode_t vp, off_t offs, off_t len,
     nfsv4stateid_t *stateidp, struct nfsvattr *nap, int *attrflagp,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsnode *np = VTONFS(vp);
 	int error, wccflag;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_DEALLOCATE, vp, cred);
 	nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER);
 	txdr_hyper(offs, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	NFSWRITEGETATTR_ATTRBIT(&attrbits);
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	wccflag = 0;
 	error = nfscl_wcc_data(nd, vp, nap, attrflagp, &wccflag, NULL);
 	if (error != 0)
 		goto nfsmout;
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, nap);
 		if (error != 0)
 			goto nfsmout;
 		*attrflagp = NFS_LATTR_NOSHRINK;
 	}
 	NFSWRITERPC_SETTIME(wccflag, np, nap, 1);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	return (error);
 }
 
 /*
  * nfs mknod rpc
  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
  * mode set to specify the file type and the size field for rdev.
  */
 int
 nfsrpc_mknod(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     u_int32_t rdev, __enum_uint8(vtype) vtyp, struct ucred *cred, NFSPROC_T *p,
     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
     int *attrflagp, int *dattrflagp)
 {
 	u_int32_t *tl;
 	int error = 0;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*nfhpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_MKNOD, dvp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		if (vtyp == VBLK || vtyp == VCHR) {
 			NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 			*tl++ = vtonfsv34_type(vtyp);
 			*tl++ = txdr_unsigned(NFSMAJOR(rdev));
 			*tl = txdr_unsigned(NFSMINOR(rdev));
 		} else {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = vtonfsv34_type(vtyp);
 		}
 	}
 	(void) nfsm_strtom(nd, name, namelen);
 	if (nd->nd_flag & ND_NFSV3) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = vtonfsv34_type(vtyp);
 	}
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 		nfscl_fillsattr(nd, vap, dvp, 0, 0);
 	if ((nd->nd_flag & ND_NFSV3) &&
 	    (vtyp == VCHR || vtyp == VBLK)) {
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		*tl++ = txdr_unsigned(NFSMAJOR(rdev));
 		*tl = txdr_unsigned(NFSMINOR(rdev));
 	}
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSGETATTR_ATTRBIT(&attrbits);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	if (nd->nd_flag & ND_NFSV2)
 		nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZERDEV, rdev);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV4)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (!nd->nd_repstat) {
 		if (nd->nd_flag & ND_NFSV4) {
 			NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 			error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 			if (error)
 				goto nfsmout;
 		}
 		error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 		if (error)
 			goto nfsmout;
 	}
 	if (nd->nd_flag & ND_NFSV3)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (!error && nd->nd_repstat)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs file create call
  * Mostly just call the approriate routine. (I separated out v4, so that
  * error recovery wouldn't be as difficult.)
  */
 int
 nfsrpc_create(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     nfsquad_t cverf, int fmode, struct ucred *cred, NFSPROC_T *p,
     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
     int *attrflagp, int *dattrflagp)
 {
 	int error = 0, newone, expireret = 0, retrycnt, unlocked;
 	struct nfsclowner *owp;
 	struct nfscldeleg *dp;
 	struct nfsmount *nmp = VFSTONFS(dvp->v_mount);
 	u_int32_t clidrev;
 
 	if (NFSHASNFSV4(nmp)) {
 	    retrycnt = 0;
 	    do {
 		dp = NULL;
 		error = nfscl_open(dvp, NULL, 0, (NFSV4OPEN_ACCESSWRITE |
 		    NFSV4OPEN_ACCESSREAD), 0, cred, p, &owp, NULL, &newone,
 		    NULL, 1, true);
 		if (error)
 			return (error);
 		if (nmp->nm_clp != NULL)
 			clidrev = nmp->nm_clp->nfsc_clientidrev;
 		else
 			clidrev = 0;
 		if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
 		    nfs_numnfscbd == 0 || retrycnt > 0)
 			error = nfsrpc_createv4(dvp, name, namelen, vap, cverf,
 			  fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
 			  attrflagp, dattrflagp, &unlocked);
 		else
 			error = nfsrpc_getcreatelayout(dvp, name, namelen, vap,
 			  cverf, fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
 			  attrflagp, dattrflagp, &unlocked);
 		/*
 		 * There is no need to invalidate cached attributes here,
 		 * since new post-delegation issue attributes are always
 		 * returned by nfsrpc_createv4() and these will update the
 		 * attribute cache.
 		 */
 		if (dp != NULL)
 			(void) nfscl_deleg(nmp->nm_mountp, owp->nfsow_clp,
 			    (*nfhpp)->nfh_fh, (*nfhpp)->nfh_len, cred, p, &dp);
 		nfscl_ownerrelease(nmp, owp, error, newone, unlocked);
 		if (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_open");
 		} else if ((error == NFSERR_EXPIRED ||
 		    error == NFSERR_BADSTATEID) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 			retrycnt++;
 		}
 	    } while (error == NFSERR_GRACE || error == NFSERR_STALECLIENTID ||
 		error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		error == NFSERR_BADSESSION ||
 		((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 		 expireret == 0 && clidrev != 0 && retrycnt < 4));
 	    if (error && retrycnt >= 4)
 		    error = EIO;
 	} else {
 		error = nfsrpc_createv23(dvp, name, namelen, vap, cverf,
 		    fmode, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp);
 	}
 	return (error);
 }
 
 /*
  * The create rpc for v2 and 3.
  */
 static int
 nfsrpc_createv23(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     nfsquad_t cverf, int fmode, struct ucred *cred, NFSPROC_T *p,
     struct nfsvattr *dnap, struct nfsvattr *nnap, struct nfsfh **nfhpp,
     int *attrflagp, int *dattrflagp)
 {
 	u_int32_t *tl;
 	int error = 0;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 
 	*nfhpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_CREATE, dvp, cred);
 	(void) nfsm_strtom(nd, name, namelen);
 	if (nd->nd_flag & ND_NFSV3) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		if (fmode & O_EXCL) {
 			*tl = txdr_unsigned(NFSCREATE_EXCLUSIVE);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 			*tl++ = cverf.lval[0];
 			*tl = cverf.lval[1];
 		} else {
 			*tl = txdr_unsigned(NFSCREATE_UNCHECKED);
 			nfscl_fillsattr(nd, vap, dvp, 0, 0);
 		}
 	} else {
 		nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZE0, 0);
 	}
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 		if (error)
 			goto nfsmout;
 	}
 	if (nd->nd_flag & ND_NFSV3)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 static int
 nfsrpc_createv4(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
     int *dattrflagp, int *unlockedp)
 {
 	u_int32_t *tl;
 	int error = 0, deleg, newone, ret, acesize, limitby;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsclopen *op;
 	struct nfscldeleg *dp = NULL;
 	struct nfsnode *np;
 	struct nfsfh *nfhp;
 	nfsattrbit_t attrbits;
 	nfsv4stateid_t stateid;
 	u_int32_t rflags;
 	struct nfsmount *nmp;
 	struct nfsclsession *tsep;
 
 	nmp = VFSTONFS(dvp->v_mount);
 	np = VTONFS(dvp);
 	*unlockedp = 0;
 	*nfhpp = NULL;
 	*dpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_CREATE, dvp, cred);
 	/*
 	 * For V4, this is actually an Open op.
 	 */
 	NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(owp->nfsow_seqid);
 	*tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
 	    NFSV4OPEN_ACCESSREAD);
 	*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	(void) nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
 	if (fmode & O_EXCL) {
 		if (NFSHASNFSV4N(nmp)) {
 			if (NFSHASSESSPERSIST(nmp)) {
 				/* Use GUARDED for persistent sessions. */
 				*tl = txdr_unsigned(NFSCREATE_GUARDED);
 				nfscl_fillsattr(nd, vap, dvp, 0, 0);
 			} else {
 				/* Otherwise, use EXCLUSIVE4_1. */
 				*tl = txdr_unsigned(NFSCREATE_EXCLUSIVE41);
 				NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 				*tl++ = cverf.lval[0];
 				*tl = cverf.lval[1];
 				nfscl_fillsattr(nd, vap, dvp, 0, 0);
 			}
 		} else {
 			/* NFSv4.0 */
 			*tl = txdr_unsigned(NFSCREATE_EXCLUSIVE);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 			*tl++ = cverf.lval[0];
 			*tl = cverf.lval[1];
 		}
 	} else {
 		*tl = txdr_unsigned(NFSCREATE_UNCHECKED);
 		nfscl_fillsattr(nd, vap, dvp, 0, 0);
 	}
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
 	(void) nfsm_strtom(nd, name, namelen);
 	/* Get the new file's handle and attributes. */
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	(void) nfsrv_putattrbit(nd, &attrbits);
 	/* Get the directory's post-op attributes. */
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_PUTFH);
 	(void)nfsm_fhtom(nmp, nd, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	(void) nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	NFSCL_INCRSEQID(owp->nfsow_seqid, nd);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 		    6 * NFSX_UNSIGNED);
 		stateid.seqid = *tl++;
 		stateid.other[0] = *tl++;
 		stateid.other[1] = *tl++;
 		stateid.other[2] = *tl;
 		rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		if (error)
 			goto nfsmout;
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		deleg = fxdr_unsigned(int, *tl);
 		if (deleg == NFSV4OPEN_DELEGATEREAD ||
 		    deleg == NFSV4OPEN_DELEGATEWRITE) {
 			if (!(owp->nfsow_clp->nfsc_flags &
 			      NFSCLFLAGS_FIRSTDELEG))
 				owp->nfsow_clp->nfsc_flags |=
 				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
 			dp = malloc(
 			    sizeof (struct nfscldeleg) + NFSX_V4FHMAX,
 			    M_NFSCLDELEG, M_WAITOK);
 			LIST_INIT(&dp->nfsdl_owner);
 			LIST_INIT(&dp->nfsdl_lock);
 			dp->nfsdl_clp = owp->nfsow_clp;
 			newnfs_copyincred(cred, &dp->nfsdl_cred);
 			nfscl_lockinit(&dp->nfsdl_rwlock);
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 			    NFSX_UNSIGNED);
 			dp->nfsdl_stateid.seqid = *tl++;
 			dp->nfsdl_stateid.other[0] = *tl++;
 			dp->nfsdl_stateid.other[1] = *tl++;
 			dp->nfsdl_stateid.other[2] = *tl++;
 			ret = fxdr_unsigned(int, *tl);
 			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
 				dp->nfsdl_flags = NFSCLDL_WRITE;
 				/*
 				 * Indicates how much the file can grow.
 				 */
 				NFSM_DISSECT(tl, u_int32_t *,
 				    3 * NFSX_UNSIGNED);
 				limitby = fxdr_unsigned(int, *tl++);
 				switch (limitby) {
 				case NFSV4OPEN_LIMITSIZE:
 					dp->nfsdl_sizelimit = fxdr_hyper(tl);
 					break;
 				case NFSV4OPEN_LIMITBLOCKS:
 					dp->nfsdl_sizelimit =
 					    fxdr_unsigned(u_int64_t, *tl++);
 					dp->nfsdl_sizelimit *=
 					    fxdr_unsigned(u_int64_t, *tl);
 					break;
 				default:
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 			} else {
 				dp->nfsdl_flags = NFSCLDL_READ;
 			}
 			if (ret)
 				dp->nfsdl_flags |= NFSCLDL_RECALL;
 			error = nfsrv_dissectace(nd, &dp->nfsdl_ace, false,
 			    &ret, &acesize, p);
 			if (error)
 				goto nfsmout;
 		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 		if (error)
 			goto nfsmout;
 		/* Get rid of the PutFH and Getattr status values. */
 		NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 		/* Load the directory attributes. */
 		error = nfsm_loadattr(nd, dnap);
 		if (error)
 			goto nfsmout;
 		*dattrflagp = 1;
 		if (dp != NULL && *attrflagp) {
 			dp->nfsdl_change = nnap->na_filerev;
 			dp->nfsdl_modtime = nnap->na_mtime;
 			dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 		}
 		/*
 		 * We can now complete the Open state.
 		 */
 		nfhp = *nfhpp;
 		if (dp != NULL) {
 			dp->nfsdl_fhlen = nfhp->nfh_len;
 			NFSBCOPY(nfhp->nfh_fh, dp->nfsdl_fh, nfhp->nfh_len);
 		}
 		/*
 		 * Get an Open structure that will be
 		 * attached to the OpenOwner, acquired already.
 		 */
 		error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len, 
 		    (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
 		    cred, p, NULL, &op, &newone, NULL, 0, false);
 		if (error)
 			goto nfsmout;
 		op->nfso_stateid = stateid;
 		newnfs_copyincred(cred, &op->nfso_cred);
 		if ((rflags & NFSV4OPEN_RESULTCONFIRM)) {
 		    do {
 			ret = nfsrpc_openconfirm(dvp, nfhp->nfh_fh,
 			    nfhp->nfh_len, op, cred, p);
 			if (ret == NFSERR_DELAY)
 			    (void) nfs_catnap(PZERO, ret, "nfs_create");
 		    } while (ret == NFSERR_DELAY);
 		    error = ret;
 		}
 
 		/*
 		 * If the server is handing out delegations, but we didn't
 		 * get one because an OpenConfirm was required, try the
 		 * Open again, to get a delegation. This is a harmless no-op,
 		 * from a server's point of view.
 		 */
 		if ((rflags & NFSV4OPEN_RESULTCONFIRM) &&
 		    (owp->nfsow_clp->nfsc_flags & NFSCLFLAGS_GOTDELEG) &&
 		    !error && dp == NULL) {
 		    KASSERT(!NFSHASNFSV4N(nmp),
 			("nfsrpc_createv4: result confirm"));
 		    do {
 			ret = nfsrpc_openrpc(VFSTONFS(dvp->v_mount), dvp,
 			    np->n_fhp->nfh_fh, np->n_fhp->nfh_len,
 			    nfhp->nfh_fh, nfhp->nfh_len,
 			    (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), op,
 			    name, namelen, &dp, 0, 0x0, cred, p, 0, 1);
 			if (ret == NFSERR_DELAY)
 			    (void) nfs_catnap(PZERO, ret, "nfs_crt2");
 		    } while (ret == NFSERR_DELAY);
 		    if (ret) {
 			if (dp != NULL) {
 				free(dp, M_NFSCLDELEG);
 				dp = NULL;
 			}
 			if (ret == NFSERR_STALECLIENTID ||
 			    ret == NFSERR_STALEDONTRECOVER ||
 			    ret == NFSERR_BADSESSION)
 				error = ret;
 		    }
 		}
 		nfscl_openrelease(nmp, op, error, newone);
 		*unlockedp = 1;
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	if (error == NFSERR_STALECLIENTID)
 		nfscl_initiate_recovery(owp->nfsow_clp);
 nfsmout:
 	if (!error)
 		*dpp = dp;
 	else if (dp != NULL)
 		free(dp, M_NFSCLDELEG);
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Nfs remove rpc
  */
 int
 nfsrpc_remove(vnode_t dvp, char *name, int namelen, vnode_t vp,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap, int *dattrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsnode *np;
 	struct nfsmount *nmp;
 	nfsv4stateid_t dstateid;
 	int error, ret = 0, i;
 
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	nmp = VFSTONFS(dvp->v_mount);
 tryagain:
 	if (NFSHASNFSV4(nmp) && ret == 0) {
 		ret = nfscl_removedeleg(vp, p, &dstateid);
 		if (ret == 1) {
 			NFSCL_REQSTART(nd, NFSPROC_RETDELEGREMOVE, vp, cred);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID +
 			    NFSX_UNSIGNED);
 			if (NFSHASNFSV4N(nmp))
 				*tl++ = 0;
 			else
 				*tl++ = dstateid.seqid;
 			*tl++ = dstateid.other[0];
 			*tl++ = dstateid.other[1];
 			*tl++ = dstateid.other[2];
 			*tl = txdr_unsigned(NFSV4OP_PUTFH);
 			np = VTONFS(dvp);
 			(void)nfsm_fhtom(nmp, nd, np->n_fhp->nfh_fh,
 			    np->n_fhp->nfh_len, 0);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_REMOVE);
 		}
 	} else {
 		ret = 0;
 	}
 	if (ret == 0)
 		NFSCL_REQSTART(nd, NFSPROC_REMOVE, dvp, cred);
 	(void) nfsm_strtom(nd, name, namelen);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 		/* For NFSv4, parse out any Delereturn replies. */
 		if (ret > 0 && nd->nd_repstat != 0 &&
 		    (nd->nd_flag & ND_NOMOREDATA)) {
 			/*
 			 * If the Delegreturn failed, try again without
 			 * it. The server will Recall, as required.
 			 */
 			m_freem(nd->nd_mrep);
 			goto tryagain;
 		}
 		for (i = 0; i < (ret * 2); i++) {
 			if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 			    ND_NFSV4) {
 			    NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			    if (*(tl + 1))
 				nd->nd_flag |= ND_NOMOREDATA;
 			}
 		}
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	}
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do an nfs rename rpc.
  */
 int
 nfsrpc_rename(vnode_t fdvp, vnode_t fvp, char *fnameptr, int fnamelen,
     vnode_t tdvp, vnode_t tvp, char *tnameptr, int tnamelen, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *fnap, struct nfsvattr *tnap,
     int *fattrflagp, int *tattrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	struct nfsnode *np;
 	nfsattrbit_t attrbits;
 	nfsv4stateid_t fdstateid, tdstateid;
 	int error = 0, ret = 0, gottd = 0, gotfd = 0, i;
 
 	*fattrflagp = 0;
 	*tattrflagp = 0;
 	nmp = VFSTONFS(fdvp->v_mount);
 	if (fnamelen > NFS_MAXNAMLEN || tnamelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 tryagain:
 	if (NFSHASNFSV4(nmp) && ret == 0) {
 		ret = nfscl_renamedeleg(fvp, &fdstateid, &gotfd, tvp,
 		    &tdstateid, &gottd, p);
 		if (gotfd && gottd) {
 			NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME2, fvp, cred);
 		} else if (gotfd) {
 			NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME1, fvp, cred);
 		} else if (gottd) {
 			NFSCL_REQSTART(nd, NFSPROC_RETDELEGRENAME1, tvp, cred);
 		}
 		if (gotfd) {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 			if (NFSHASNFSV4N(nmp))
 				*tl++ = 0;
 			else
 				*tl++ = fdstateid.seqid;
 			*tl++ = fdstateid.other[0];
 			*tl++ = fdstateid.other[1];
 			*tl = fdstateid.other[2];
 			if (gottd) {
 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 				*tl = txdr_unsigned(NFSV4OP_PUTFH);
 				np = VTONFS(tvp);
 				(void)nfsm_fhtom(nmp, nd, np->n_fhp->nfh_fh,
 				    np->n_fhp->nfh_len, 0);
 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 				*tl = txdr_unsigned(NFSV4OP_DELEGRETURN);
 			}
 		}
 		if (gottd) {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 			if (NFSHASNFSV4N(nmp))
 				*tl++ = 0;
 			else
 				*tl++ = tdstateid.seqid;
 			*tl++ = tdstateid.other[0];
 			*tl++ = tdstateid.other[1];
 			*tl = tdstateid.other[2];
 		}
 		if (ret > 0) {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_PUTFH);
 			np = VTONFS(fdvp);
 			(void)nfsm_fhtom(nmp, nd, np->n_fhp->nfh_fh,
 			    np->n_fhp->nfh_len, 0);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_SAVEFH);
 		}
 	} else {
 		ret = 0;
 	}
 	if (ret == 0)
 		NFSCL_REQSTART(nd, NFSPROC_RENAME, fdvp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSWCCATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_PUTFH);
 		(void)nfsm_fhtom(nmp, nd, VTONFS(tdvp)->n_fhp->nfh_fh,
 		    VTONFS(tdvp)->n_fhp->nfh_len, 0);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		nd->nd_flag |= ND_V4WCCATTR;
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_RENAME);
 	}
 	(void) nfsm_strtom(nd, fnameptr, fnamelen);
 	if (!(nd->nd_flag & ND_NFSV4))
 		(void)nfsm_fhtom(nmp, nd, VTONFS(tdvp)->n_fhp->nfh_fh,
 			VTONFS(tdvp)->n_fhp->nfh_len, 0);
 	(void) nfsm_strtom(nd, tnameptr, tnamelen);
 	error = nfscl_request(nd, fdvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
 		/* For NFSv4, parse out any Delereturn replies. */
 		if (ret > 0 && nd->nd_repstat != 0 &&
 		    (nd->nd_flag & ND_NOMOREDATA)) {
 			/*
 			 * If the Delegreturn failed, try again without
 			 * it. The server will Recall, as required.
 			 */
 			m_freem(nd->nd_mrep);
 			goto tryagain;
 		}
 		for (i = 0; i < (ret * 2); i++) {
 			if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) ==
 			    ND_NFSV4) {
 			    NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			    if (*(tl + 1)) {
 				if (i == 0 && ret > 1) {
 				    /*
 				     * If the Delegreturn failed, try again
 				     * without it. The server will Recall, as
 				     * required.
 				     * If ret > 1, the first iteration of this
 				     * loop is the second DelegReturn result.
 				     */
 				    m_freem(nd->nd_mrep);
 				    goto tryagain;
 				} else {
 				    nd->nd_flag |= ND_NOMOREDATA;
 				}
 			    }
 			}
 		}
 		/* Now, the first wcc attribute reply. */
 		if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			if (*(tl + 1))
 				nd->nd_flag |= ND_NOMOREDATA;
 		}
 		error = nfscl_wcc_data(nd, fdvp, fnap, fattrflagp, NULL, NULL);
 		/* and the second wcc attribute reply. */
 		if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4 &&
 		    !error) {
 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			if (*(tl + 1))
 				nd->nd_flag |= ND_NOMOREDATA;
 		}
 		if (!error)
 			error = nfscl_wcc_data(nd, tdvp, tnap, tattrflagp,
 			    NULL, NULL);
 	}
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs hard link create rpc
  */
 int
 nfsrpc_link(vnode_t dvp, vnode_t vp, char *name, int namelen,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nap, int *attrflagp, int *dattrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	int error = 0;
 
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_LINK, vp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_PUTFH);
 	}
 	(void)nfsm_fhtom(VFSTONFS(dvp->v_mount), nd, VTONFS(dvp)->n_fhp->nfh_fh,
 		VTONFS(dvp)->n_fhp->nfh_len, 0);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSWCCATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		nd->nd_flag |= ND_V4WCCATTR;
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_LINK);
 	}
 	(void) nfsm_strtom(nd, name, namelen);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV3) {
 		error = nfscl_postop_attr(nd, nap, attrflagp);
 		if (!error)
 			error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp,
 			    NULL, NULL);
 	} else if ((nd->nd_flag & (ND_NFSV4 | ND_NOMOREDATA)) == ND_NFSV4) {
 		/*
 		 * First, parse out the PutFH and Getattr result.
 		 */
 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		if (!(*(tl + 1)))
 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		if (*(tl + 1))
 			nd->nd_flag |= ND_NOMOREDATA;
 		/*
 		 * Get the pre-op attributes.
 		 */
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	}
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs symbolic link create rpc
  */
 int
 nfsrpc_symlink(vnode_t dvp, char *name, int namelen, const char *target,
     struct vattr *vap, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
     int *dattrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	int slen, error = 0;
 
 	*nfhpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	nmp = VFSTONFS(dvp->v_mount);
 	slen = strlen(target);
 	if (slen > NFS_MAXPATHLEN || namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_SYMLINK, dvp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFLNK);
 		(void) nfsm_strtom(nd, target, slen);
 	}
 	(void) nfsm_strtom(nd, name, namelen);
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 		nfscl_fillsattr(nd, vap, dvp, 0, 0);
 	if (!(nd->nd_flag & ND_NFSV4))
 		(void) nfsm_strtom(nd, target, slen);
 	if (nd->nd_flag & ND_NFSV2)
 		nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZENEG1, 0);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV4)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if ((nd->nd_flag & ND_NFSV3) && !error) {
 		if (!nd->nd_repstat)
 			error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 		if (!error)
 			error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp,
 			    NULL, NULL);
 	}
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	/*
 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 	 * Only do this if vfs.nfs.ignore_eexist is set.
 	 * Never do this for NFSv4.1 or later minor versions, since sessions
 	 * should guarantee "exactly once" RPC semantics.
 	 */
 	if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
 	    nmp->nm_minorvers == 0))
 		error = 0;
 	return (error);
 }
 
 /*
  * nfs make dir rpc
  */
 int
 nfsrpc_mkdir(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
     int *dattrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	int error = 0;
 	struct nfsfh *fhp;
 	struct nfsmount *nmp;
 
 	*nfhpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	nmp = VFSTONFS(dvp->v_mount);
 	fhp = VTONFS(dvp)->n_fhp;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_MKDIR, dvp, cred);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFDIR);
 	}
 	(void) nfsm_strtom(nd, name, namelen);
 	nfscl_fillsattr(nd, vap, dvp, NFSSATTR_SIZENEG1, 0);
 	if (nd->nd_flag & ND_NFSV4) {
 		NFSGETATTR_ATTRBIT(&attrbits);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_PUTFH);
 		(void)nfsm_fhtom(nmp, nd, fhp->nfh_fh, fhp->nfh_len, 0);
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & ND_NFSV4)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (!nd->nd_repstat && !error) {
 		if (nd->nd_flag & ND_NFSV4) {
 			NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 			error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		}
 		if (!error)
 			error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 		if (error == 0 && (nd->nd_flag & ND_NFSV4) != 0) {
 			/* Get rid of the PutFH and Getattr status values. */
 			NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 			/* Load the directory attributes. */
 			error = nfsm_loadattr(nd, dnap);
 			if (error == 0)
 				*dattrflagp = 1;
 		}
 	}
 	if ((nd->nd_flag & ND_NFSV3) && !error)
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	/*
 	 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 	 * Only do this if vfs.nfs.ignore_eexist is set.
 	 * Never do this for NFSv4.1 or later minor versions, since sessions
 	 * should guarantee "exactly once" RPC semantics.
 	 */
 	if (error == EEXIST && nfsignore_eexist != 0 && (!NFSHASNFSV4(nmp) ||
 	    nmp->nm_minorvers == 0))
 		error = 0;
 	return (error);
 }
 
 /*
  * nfs remove directory call
  */
 int
 nfsrpc_rmdir(vnode_t dvp, char *name, int namelen, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *dnap, int *dattrflagp)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error = 0;
 
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_RMDIR, dvp, cred);
 	(void) nfsm_strtom(nd, name, namelen);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4))
 		error = nfscl_wcc_data(nd, dvp, dnap, dattrflagp, NULL, NULL);
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	/*
 	 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
 	 */
 	if (error == ENOENT)
 		error = 0;
 	return (error);
 }
 
 /*
  * Readdir rpc.
  * Always returns with either uio_resid unchanged, if you are at the
  * end of the directory, or uio_resid == 0, with all DIRBLKSIZ chunks
  * filled in.
  * I felt this would allow caching of directory blocks more easily
  * than returning a pertially filled block.
  * Directory offset cookies:
  * Oh my, what to do with them...
  * I can think of three ways to deal with them:
  * 1 - have the layer above these RPCs maintain a map between logical
  *     directory byte offsets and the NFS directory offset cookies
  * 2 - pass the opaque directory offset cookies up into userland
  *     and let the libc functions deal with them, via the system call
  * 3 - return them to userland in the "struct dirent", so future versions
  *     of libc can use them and do whatever is necessary to make things work
  *     above these rpc calls, in the meantime
  * For now, I do #3 by "hiding" the directory offset cookies after the
  * d_name field in struct dirent. This is space inside d_reclen that
  * will be ignored by anything that doesn't know about them.
  * The directory offset cookies are filled in as the last 8 bytes of
  * each directory entry, after d_name. Someday, the userland libc
  * functions may be able to use these. In the meantime, it satisfies
  * OpenBSD's requirements for cookies being returned.
  * If expects the directory offset cookie for the read to be in uio_offset
  * and returns the one for the next entry after this directory block in
  * there, as well.
  */
 int
 nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
     int *eofp)
 {
 	int len, left;
 	struct dirent *dp = NULL;
 	u_int32_t *tl;
 	nfsquad_t cookie, ncookie;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *dnp = VTONFS(vp);
 	struct nfsvattr nfsva;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
 	int reqsize, tryformoredirs = 1, readsize, eof = 0, gotmnton = 0;
 	u_int64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX;
 	char *cp;
 	nfsattrbit_t attrbits, dattrbits;
 	u_int32_t rderr, *tl2 = NULL;
 	size_t tresid;
 
 	KASSERT(uiop->uio_iovcnt == 1 &&
 	    (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
 	    ("nfs readdirrpc bad uio"));
 	ncookie.lval[0] = ncookie.lval[1] = 0;
 	/*
 	 * There is no point in reading a lot more than uio_resid, however
 	 * adding one additional DIRBLKSIZ makes sense. Since uio_resid
 	 * and nm_readdirsize are both exact multiples of DIRBLKSIZ, this
 	 * will never make readsize > nm_readdirsize.
 	 */
 	readsize = nmp->nm_readdirsize;
 	if (readsize > uiop->uio_resid)
 		readsize = uiop->uio_resid + DIRBLKSIZ;
 
 	*attrflagp = 0;
 	if (eofp)
 		*eofp = 0;
 	tresid = uiop->uio_resid;
 	cookie.lval[0] = cookiep->nfsuquad[0];
 	cookie.lval[1] = cookiep->nfsuquad[1];
 	nd->nd_mrep = NULL;
 
 	/*
 	 * For NFSv4, first create the "." and ".." entries.
 	 */
 	if (NFSHASNFSV4(nmp)) {
 		reqsize = 6 * NFSX_UNSIGNED;
 		NFSGETATTR_ATTRBIT(&dattrbits);
 		NFSZERO_ATTRBIT(&attrbits);
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FILEID);
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TYPE);
 		if (NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
 		    NFSATTRBIT_MOUNTEDONFILEID)) {
 			NFSSETBIT_ATTRBIT(&attrbits,
 			    NFSATTRBIT_MOUNTEDONFILEID);
 			gotmnton = 1;
 		} else {
 			/*
 			 * Must fake it. Use the fileno, except when the
 			 * fsid is != to that of the directory. For that
 			 * case, generate a fake fileno that is not the same.
 			 */
 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FSID);
 			gotmnton = 0;
 		}
 
 		/*
 		 * Joy, oh joy. For V4 we get to hand craft '.' and '..'.
 		 */
 		if (uiop->uio_offset == 0) {
 			NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp, cred);
 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 			*tl = txdr_unsigned(NFSV4OP_GETATTR);
 			(void) nfsrv_putattrbit(nd, &attrbits);
 			error = nfscl_request(nd, vp, p, cred);
 			if (error)
 			    return (error);
 			dotfileid = 0;	/* Fake out the compiler. */
 			if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 			    error = nfsm_loadattr(nd, &nfsva);
 			    if (error != 0)
 				goto nfsmout;
 			    dotfileid = nfsva.na_fileid;
 			}
 			if (nd->nd_repstat == 0) {
 			    NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 			    len = fxdr_unsigned(int, *(tl + 4));
 			    if (len > 0 && len <= NFSX_V4FHMAX)
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 			    else
 				error = EPERM;
 			    if (!error) {
 				NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 				nfsva.na_mntonfileno = UINT64_MAX;
 				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 				    NULL, NULL, NULL, p, cred);
 				if (error) {
 				    dotdotfileid = dotfileid;
 				} else if (gotmnton) {
 				    if (nfsva.na_mntonfileno != UINT64_MAX)
 					dotdotfileid = nfsva.na_mntonfileno;
 				    else
 					dotdotfileid = nfsva.na_fileid;
 				} else if (nfsva.na_filesid[0] ==
 				    dnp->n_vattr.na_filesid[0] &&
 				    nfsva.na_filesid[1] ==
 				    dnp->n_vattr.na_filesid[1]) {
 				    dotdotfileid = nfsva.na_fileid;
 				} else {
 				    do {
 					fakefileno--;
 				    } while (fakefileno ==
 					nfsva.na_fileid);
 				    dotdotfileid = fakefileno;
 				}
 			    }
 			} else if (nd->nd_repstat == NFSERR_NOENT) {
 			    /*
 			     * Lookupp returns NFSERR_NOENT when we are
 			     * at the root, so just use the current dir.
 			     */
 			    nd->nd_repstat = 0;
 			    dotdotfileid = dotfileid;
 			} else {
 			    error = nd->nd_repstat;
 			}
 			m_freem(nd->nd_mrep);
 			if (error)
 			    return (error);
 			nd->nd_mrep = NULL;
 			dp = (struct dirent *)uiop->uio_iov->iov_base;
 			dp->d_pad0 = dp->d_pad1 = 0;
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotfileid;
 			dp->d_namlen = 1;
 			*((uint64_t *)dp->d_name) = 0;	/* Zero pad it. */
 			dp->d_name[0] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
 			blksiz += dp->d_reclen;
 			uiop->uio_resid -= dp->d_reclen;
 			uiop->uio_offset += dp->d_reclen;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base + dp->d_reclen;
 			uiop->uio_iov->iov_len -= dp->d_reclen;
 			dp = (struct dirent *)uiop->uio_iov->iov_base;
 			dp->d_pad0 = dp->d_pad1 = 0;
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotdotfileid;
 			dp->d_namlen = 2;
 			*((uint64_t *)dp->d_name) = 0;
 			dp->d_name[0] = '.';
 			dp->d_name[1] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
 			blksiz += dp->d_reclen;
 			uiop->uio_resid -= dp->d_reclen;
 			uiop->uio_offset += dp->d_reclen;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base + dp->d_reclen;
 			uiop->uio_iov->iov_len -= dp->d_reclen;
 		}
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_RDATTRERROR);
 	} else {
 		reqsize = 5 * NFSX_UNSIGNED;
 	}
 
 	/*
 	 * Loop around doing readdir rpc's of size readsize.
 	 * The stopping criteria is EOF or buffer full.
 	 */
 	while (more_dirs && bigenough) {
 		*attrflagp = 0;
 		NFSCL_REQSTART(nd, NFSPROC_READDIR, vp, cred);
 		if (nd->nd_flag & ND_NFSV2) {
 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			*tl++ = cookie.lval[1];
 			*tl = txdr_unsigned(readsize);
 		} else {
 			NFSM_BUILD(tl, u_int32_t *, reqsize);
 			*tl++ = cookie.lval[0];
 			*tl++ = cookie.lval[1];
 			if (cookie.qval == 0) {
 				*tl++ = 0;
 				*tl++ = 0;
 			} else {
 				NFSLOCKNODE(dnp);
 				*tl++ = dnp->n_cookieverf.nfsuquad[0];
 				*tl++ = dnp->n_cookieverf.nfsuquad[1];
 				NFSUNLOCKNODE(dnp);
 			}
 			if (nd->nd_flag & ND_NFSV4) {
 				*tl++ = txdr_unsigned(readsize);
 				*tl = txdr_unsigned(readsize);
 				(void) nfsrv_putattrbit(nd, &attrbits);
 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 				*tl = txdr_unsigned(NFSV4OP_GETATTR);
 				(void) nfsrv_putattrbit(nd, &dattrbits);
 			} else {
 				*tl = txdr_unsigned(readsize);
 			}
 		}
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (!(nd->nd_flag & ND_NFSV2)) {
 			if (nd->nd_flag & ND_NFSV3)
 				error = nfscl_postop_attr(nd, nap, attrflagp);
 			if (!nd->nd_repstat && !error) {
 				NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
 				NFSLOCKNODE(dnp);
 				dnp->n_cookieverf.nfsuquad[0] = *tl++;
 				dnp->n_cookieverf.nfsuquad[1] = *tl;
 				NFSUNLOCKNODE(dnp);
 			}
 		}
 		if (nd->nd_repstat || error) {
 			if (!error)
 				error = nd->nd_repstat;
 			goto nfsmout;
 		}
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		more_dirs = fxdr_unsigned(int, *tl);
 		if (!more_dirs)
 			tryformoredirs = 0;
 
 		/* loop through the dir entries, doctoring them to 4bsd form */
 		while (more_dirs && bigenough) {
 			if (nd->nd_flag & ND_NFSV4) {
 				NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 				ncookie.lval[0] = *tl++;
 				ncookie.lval[1] = *tl++;
 				len = fxdr_unsigned(int, *tl);
 			} else if (nd->nd_flag & ND_NFSV3) {
 				NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 				nfsva.na_fileid = fxdr_hyper(tl);
 				tl += 2;
 				len = fxdr_unsigned(int, *tl);
 			} else {
 				NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 				nfsva.na_fileid = fxdr_unsigned(uint64_t,
 				    *tl++);
 				len = fxdr_unsigned(int, *tl);
 			}
 			if (len <= 0 || len > NFS_MAXNAMLEN) {
 				error = EBADRPC;
 				goto nfsmout;
 			}
 			tlen = roundup2(len, 8);
 			if (tlen == len)
 				tlen += 8;  /* To ensure null termination. */
 			left = DIRBLKSIZ - blksiz;
 			if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
 				NFSBZERO(uiop->uio_iov->iov_base, left);
 				dp->d_reclen += left;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + left;
 				uiop->uio_iov->iov_len -= left;
 				uiop->uio_resid -= left;
 				uiop->uio_offset += left;
 				blksiz = 0;
 			}
 			if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
 			    uiop->uio_resid)
 				bigenough = 0;
 			if (bigenough) {
 				dp = (struct dirent *)uiop->uio_iov->iov_base;
 				dp->d_pad0 = dp->d_pad1 = 0;
 				dp->d_off = 0;
 				dp->d_namlen = len;
 				dp->d_reclen = _GENERIC_DIRLEN(len) +
 				    NFSX_HYPER;
 				dp->d_type = DT_UNKNOWN;
 				blksiz += dp->d_reclen;
 				if (blksiz == DIRBLKSIZ)
 					blksiz = 0;
 				uiop->uio_resid -= DIRHDSIZ;
 				uiop->uio_offset += DIRHDSIZ;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
 				uiop->uio_iov->iov_len -= DIRHDSIZ;
 				error = nfsm_mbufuio(nd, uiop, len);
 				if (error)
 					goto nfsmout;
 				cp = uiop->uio_iov->iov_base;
 				tlen -= len;
 				NFSBZERO(cp, tlen);
 				cp += tlen;	/* points to cookie storage */
 				tl2 = (u_int32_t *)cp;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + tlen +
 				    NFSX_HYPER;
 				uiop->uio_iov->iov_len -= tlen + NFSX_HYPER;
 				uiop->uio_resid -= tlen + NFSX_HYPER;
 				uiop->uio_offset += (tlen + NFSX_HYPER);
 			} else {
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 				if (error)
 					goto nfsmout;
 			}
 			if (nd->nd_flag & ND_NFSV4) {
 				rderr = 0;
 				nfsva.na_mntonfileno = UINT64_MAX;
 				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 				    NULL, NULL, &rderr, p, cred);
 				if (error)
 					goto nfsmout;
 				NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			} else if (nd->nd_flag & ND_NFSV3) {
 				NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 				ncookie.lval[0] = *tl++;
 				ncookie.lval[1] = *tl++;
 			} else {
 				NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 				ncookie.lval[0] = 0;
 				ncookie.lval[1] = *tl++;
 			}
 			if (bigenough) {
 			    if (nd->nd_flag & ND_NFSV4) {
 				if (rderr) {
 				    dp->d_fileno = 0;
 				} else {
 				    if (gotmnton) {
 					if (nfsva.na_mntonfileno != UINT64_MAX)
 					    dp->d_fileno = nfsva.na_mntonfileno;
 					else
 					    dp->d_fileno = nfsva.na_fileid;
 				    } else if (nfsva.na_filesid[0] ==
 					dnp->n_vattr.na_filesid[0] &&
 					nfsva.na_filesid[1] ==
 					dnp->n_vattr.na_filesid[1]) {
 					dp->d_fileno = nfsva.na_fileid;
 				    } else {
 					do {
 					    fakefileno--;
 					} while (fakefileno ==
 					    nfsva.na_fileid);
 					dp->d_fileno = fakefileno;
 				    }
 				    dp->d_type = vtonfs_dtype(nfsva.na_type);
 				}
 			    } else {
 				dp->d_fileno = nfsva.na_fileid;
 			    }
 			    *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] =
 				ncookie.lval[0];
 			    *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] =
 				ncookie.lval[1];
 			}
 			more_dirs = fxdr_unsigned(int, *tl);
 		}
 		/*
 		 * If at end of rpc data, get the eof boolean
 		 */
 		if (!more_dirs) {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			eof = fxdr_unsigned(int, *tl);
 			if (tryformoredirs)
 				more_dirs = !eof;
 			if (nd->nd_flag & ND_NFSV4) {
 				error = nfscl_postop_attr(nd, nap, attrflagp);
 				if (error)
 					goto nfsmout;
 			}
 		}
 		m_freem(nd->nd_mrep);
 		nd->nd_mrep = NULL;
 	}
 	/*
 	 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 	 * by increasing d_reclen for the last record.
 	 */
 	if (blksiz > 0) {
 		left = DIRBLKSIZ - blksiz;
 		NFSBZERO(uiop->uio_iov->iov_base, left);
 		dp->d_reclen += left;
 		uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
 		    left;
 		uiop->uio_iov->iov_len -= left;
 		uiop->uio_resid -= left;
 		uiop->uio_offset += left;
 	}
 
 	/*
 	 * If returning no data, assume end of file.
 	 * If not bigenough, return not end of file, since you aren't
 	 *    returning all the data
 	 * Otherwise, return the eof flag from the server.
 	 */
 	if (eofp) {
 		if (tresid == ((size_t)(uiop->uio_resid)))
 			*eofp = 1;
 		else if (!bigenough)
 			*eofp = 0;
 		else
 			*eofp = eof;
 	}
 
 	/*
 	 * Add extra empty records to any remaining DIRBLKSIZ chunks.
 	 */
 	while (uiop->uio_resid > 0 && uiop->uio_resid != tresid) {
 		dp = (struct dirent *)uiop->uio_iov->iov_base;
 		NFSBZERO(dp, DIRBLKSIZ);
 		dp->d_type = DT_UNKNOWN;
 		tl = (u_int32_t *)&dp->d_name[4];
 		*tl++ = cookie.lval[0];
 		*tl = cookie.lval[1];
 		dp->d_reclen = DIRBLKSIZ;
 		uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
 		    DIRBLKSIZ;
 		uiop->uio_iov->iov_len -= DIRBLKSIZ;
 		uiop->uio_resid -= DIRBLKSIZ;
 		uiop->uio_offset += DIRBLKSIZ;
 	}
 
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * NFS V3 readdir plus RPC. Used in place of nfsrpc_readdir().
  * (Also used for NFS V4 when mount flag set.)
  * (ditto above w.r.t. multiple of DIRBLKSIZ, etc.)
  */
 int
 nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp,
     int *eofp)
 {
 	int len, left;
 	struct dirent *dp = NULL;
 	u_int32_t *tl;
 	vnode_t newvp = NULLVP;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nameidata nami, *ndp = &nami;
 	struct componentname *cnp = &ndp->ni_cnd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *dnp = VTONFS(vp), *np;
 	struct nfsvattr nfsva;
 	struct nfsfh *nfhp;
 	nfsquad_t cookie, ncookie;
 	int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
 	int attrflag, tryformoredirs = 1, eof = 0, gotmnton = 0;
 	int isdotdot = 0, unlocknewvp = 0;
 	u_int64_t dotfileid, dotdotfileid = 0, fakefileno = UINT64_MAX;
 	u_int64_t fileno = 0;
 	char *cp;
 	nfsattrbit_t attrbits, dattrbits;
 	size_t tresid;
 	u_int32_t *tl2 = NULL, rderr;
 	struct timespec dctime, ts;
 	bool attr_ok;
 
 	KASSERT(uiop->uio_iovcnt == 1 &&
 	    (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
 	    ("nfs readdirplusrpc bad uio"));
 	ncookie.lval[0] = ncookie.lval[1] = 0;
 	timespecclear(&dctime);
 	*attrflagp = 0;
 	if (eofp != NULL)
 		*eofp = 0;
 	ndp->ni_dvp = vp;
 	nd->nd_mrep = NULL;
 	cookie.lval[0] = cookiep->nfsuquad[0];
 	cookie.lval[1] = cookiep->nfsuquad[1];
 	tresid = uiop->uio_resid;
 
 	/*
 	 * For NFSv4, first create the "." and ".." entries.
 	 */
 	if (NFSHASNFSV4(nmp)) {
 		NFSGETATTR_ATTRBIT(&dattrbits);
 		NFSZERO_ATTRBIT(&attrbits);
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FILEID);
 		if (NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
 		    NFSATTRBIT_MOUNTEDONFILEID)) {
 			NFSSETBIT_ATTRBIT(&attrbits,
 			    NFSATTRBIT_MOUNTEDONFILEID);
 			gotmnton = 1;
 		} else {
 			/*
 			 * Must fake it. Use the fileno, except when the
 			 * fsid is != to that of the directory. For that
 			 * case, generate a fake fileno that is not the same.
 			 */
 			NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_FSID);
 			gotmnton = 0;
 		}
 
 		/*
 		 * Joy, oh joy. For V4 we get to hand craft '.' and '..'.
 		 */
 		if (uiop->uio_offset == 0) {
 			NFSCL_REQSTART(nd, NFSPROC_LOOKUPP, vp, cred);
 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 			*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 			*tl = txdr_unsigned(NFSV4OP_GETATTR);
 			(void) nfsrv_putattrbit(nd, &attrbits);
 			error = nfscl_request(nd, vp, p, cred);
 			if (error)
 			    return (error);
 			dotfileid = 0;	/* Fake out the compiler. */
 			if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 			    error = nfsm_loadattr(nd, &nfsva);
 			    if (error != 0)
 				goto nfsmout;
 			    dctime = nfsva.na_ctime;
 			    dotfileid = nfsva.na_fileid;
 			}
 			if (nd->nd_repstat == 0) {
 			    NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 			    len = fxdr_unsigned(int, *(tl + 4));
 			    if (len > 0 && len <= NFSX_V4FHMAX)
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 			    else
 				error = EPERM;
 			    if (!error) {
 				NFSM_DISSECT(tl, u_int32_t *, 2*NFSX_UNSIGNED);
 				nfsva.na_mntonfileno = UINT64_MAX;
 				error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 				    NULL, NULL, NULL, p, cred);
 				if (error) {
 				    dotdotfileid = dotfileid;
 				} else if (gotmnton) {
 				    if (nfsva.na_mntonfileno != UINT64_MAX)
 					dotdotfileid = nfsva.na_mntonfileno;
 				    else
 					dotdotfileid = nfsva.na_fileid;
 				} else if (nfsva.na_filesid[0] ==
 				    dnp->n_vattr.na_filesid[0] &&
 				    nfsva.na_filesid[1] ==
 				    dnp->n_vattr.na_filesid[1]) {
 				    dotdotfileid = nfsva.na_fileid;
 				} else {
 				    do {
 					fakefileno--;
 				    } while (fakefileno ==
 					nfsva.na_fileid);
 				    dotdotfileid = fakefileno;
 				}
 			    }
 			} else if (nd->nd_repstat == NFSERR_NOENT) {
 			    /*
 			     * Lookupp returns NFSERR_NOENT when we are
 			     * at the root, so just use the current dir.
 			     */
 			    nd->nd_repstat = 0;
 			    dotdotfileid = dotfileid;
 			} else {
 			    error = nd->nd_repstat;
 			}
 			m_freem(nd->nd_mrep);
 			if (error)
 			    return (error);
 			nd->nd_mrep = NULL;
 			dp = (struct dirent *)uiop->uio_iov->iov_base;
 			dp->d_pad0 = dp->d_pad1 = 0;
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotfileid;
 			dp->d_namlen = 1;
 			*((uint64_t *)dp->d_name) = 0;	/* Zero pad it. */
 			dp->d_name[0] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
 			blksiz += dp->d_reclen;
 			uiop->uio_resid -= dp->d_reclen;
 			uiop->uio_offset += dp->d_reclen;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base + dp->d_reclen;
 			uiop->uio_iov->iov_len -= dp->d_reclen;
 			dp = (struct dirent *)uiop->uio_iov->iov_base;
 			dp->d_pad0 = dp->d_pad1 = 0;
 			dp->d_off = 0;
 			dp->d_type = DT_DIR;
 			dp->d_fileno = dotdotfileid;
 			dp->d_namlen = 2;
 			*((uint64_t *)dp->d_name) = 0;
 			dp->d_name[0] = '.';
 			dp->d_name[1] = '.';
 			dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
 			/*
 			 * Just make these offset cookie 0.
 			 */
 			tl = (u_int32_t *)&dp->d_name[8];
 			*tl++ = 0;
 			*tl = 0;
 			blksiz += dp->d_reclen;
 			uiop->uio_resid -= dp->d_reclen;
 			uiop->uio_offset += dp->d_reclen;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base + dp->d_reclen;
 			uiop->uio_iov->iov_len -= dp->d_reclen;
 		}
 		NFSREADDIRPLUS_ATTRBIT(&attrbits);
 		if (gotmnton)
 			NFSSETBIT_ATTRBIT(&attrbits,
 			    NFSATTRBIT_MOUNTEDONFILEID);
 		if (!NFSISSET_ATTRBIT(&dnp->n_vattr.na_suppattr,
 		    NFSATTRBIT_TIMECREATE))
 			NFSCLRBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);
 	}
 
 	/*
 	 * Loop around doing readdir rpc's of size nm_readdirsize.
 	 * The stopping criteria is EOF or buffer full.
 	 */
 	while (more_dirs && bigenough) {
 		*attrflagp = 0;
 		NFSCL_REQSTART(nd, NFSPROC_READDIRPLUS, vp, cred);
  		NFSM_BUILD(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
 		*tl++ = cookie.lval[0];
 		*tl++ = cookie.lval[1];
 		if (cookie.qval == 0) {
 			*tl++ = 0;
 			*tl++ = 0;
 		} else {
 			NFSLOCKNODE(dnp);
 			*tl++ = dnp->n_cookieverf.nfsuquad[0];
 			*tl++ = dnp->n_cookieverf.nfsuquad[1];
 			NFSUNLOCKNODE(dnp);
 		}
 		*tl++ = txdr_unsigned(nmp->nm_readdirsize);
 		*tl = txdr_unsigned(nmp->nm_readdirsize);
 		if (nd->nd_flag & ND_NFSV4) {
 			(void) nfsrv_putattrbit(nd, &attrbits);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_GETATTR);
 			(void) nfsrv_putattrbit(nd, &dattrbits);
 		}
 		nanouptime(&ts);
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (nd->nd_flag & ND_NFSV3)
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 		if (nd->nd_repstat || error) {
 			if (!error)
 				error = nd->nd_repstat;
 			goto nfsmout;
 		}
 		if ((nd->nd_flag & ND_NFSV3) != 0 && *attrflagp != 0)
 			dctime = nap->na_ctime;
 		NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 		NFSLOCKNODE(dnp);
 		dnp->n_cookieverf.nfsuquad[0] = *tl++;
 		dnp->n_cookieverf.nfsuquad[1] = *tl++;
 		NFSUNLOCKNODE(dnp);
 		more_dirs = fxdr_unsigned(int, *tl);
 		if (!more_dirs)
 			tryformoredirs = 0;
 
 		/* loop through the dir entries, doctoring them to 4bsd form */
 		while (more_dirs && bigenough) {
 			NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 			if (nd->nd_flag & ND_NFSV4) {
 				ncookie.lval[0] = *tl++;
 				ncookie.lval[1] = *tl++;
 			} else {
 				fileno = fxdr_hyper(tl);
 				tl += 2;
 			}
 			len = fxdr_unsigned(int, *tl);
 			if (len <= 0 || len > NFS_MAXNAMLEN) {
 				error = EBADRPC;
 				goto nfsmout;
 			}
 			tlen = roundup2(len, 8);
 			if (tlen == len)
 				tlen += 8;  /* To ensure null termination. */
 			left = DIRBLKSIZ - blksiz;
 			if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
 				NFSBZERO(uiop->uio_iov->iov_base, left);
 				dp->d_reclen += left;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + left;
 				uiop->uio_iov->iov_len -= left;
 				uiop->uio_resid -= left;
 				uiop->uio_offset += left;
 				blksiz = 0;
 			}
 			if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
 			    uiop->uio_resid)
 				bigenough = 0;
 			if (bigenough) {
 				dp = (struct dirent *)uiop->uio_iov->iov_base;
 				dp->d_pad0 = dp->d_pad1 = 0;
 				dp->d_off = 0;
 				dp->d_namlen = len;
 				dp->d_reclen = _GENERIC_DIRLEN(len) +
 				    NFSX_HYPER;
 				dp->d_type = DT_UNKNOWN;
 				blksiz += dp->d_reclen;
 				if (blksiz == DIRBLKSIZ)
 					blksiz = 0;
 				uiop->uio_resid -= DIRHDSIZ;
 				uiop->uio_offset += DIRHDSIZ;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
 				uiop->uio_iov->iov_len -= DIRHDSIZ;
 				cnp->cn_nameptr = uiop->uio_iov->iov_base;
 				cnp->cn_namelen = len;
 				NFSCNHASHZERO(cnp);
 				error = nfsm_mbufuio(nd, uiop, len);
 				if (error)
 					goto nfsmout;
 				cp = uiop->uio_iov->iov_base;
 				tlen -= len;
 				NFSBZERO(cp, tlen);
 				cp += tlen;	/* points to cookie storage */
 				tl2 = (u_int32_t *)cp;
 				if (len == 2 && cnp->cn_nameptr[0] == '.' &&
 				    cnp->cn_nameptr[1] == '.')
 					isdotdot = 1;
 				else
 					isdotdot = 0;
 				uiop->uio_iov->iov_base =
 				    (char *)uiop->uio_iov->iov_base + tlen +
 				    NFSX_HYPER;
 				uiop->uio_iov->iov_len -= tlen + NFSX_HYPER;
 				uiop->uio_resid -= tlen + NFSX_HYPER;
 				uiop->uio_offset += (tlen + NFSX_HYPER);
 			} else {
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 				if (error)
 					goto nfsmout;
 			}
 			nfhp = NULL;
 			if (nd->nd_flag & ND_NFSV3) {
 				NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
 				ncookie.lval[0] = *tl++;
 				ncookie.lval[1] = *tl++;
 				attrflag = fxdr_unsigned(int, *tl);
 				if (attrflag) {
 				  error = nfsm_loadattr(nd, &nfsva);
 				  if (error)
 					goto nfsmout;
 				}
 				NFSM_DISSECT(tl,u_int32_t *,NFSX_UNSIGNED);
 				if (*tl) {
 					error = nfsm_getfh(nd, &nfhp);
 					if (error)
 					    goto nfsmout;
 				}
 				if (!attrflag && nfhp != NULL) {
 					free(nfhp, M_NFSFH);
 					nfhp = NULL;
 				}
 			} else {
 				rderr = 0;
 				nfsva.na_mntonfileno = 0xffffffff;
 				error = nfsv4_loadattr(nd, NULL, &nfsva, &nfhp,
 				    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 				    NULL, NULL, &rderr, p, cred);
 				if (error)
 					goto nfsmout;
 			}
 
 			if (bigenough) {
 			    if (nd->nd_flag & ND_NFSV4) {
 				if (rderr) {
 				    dp->d_fileno = 0;
 				} else if (gotmnton) {
 				    if (nfsva.na_mntonfileno != 0xffffffff)
 					dp->d_fileno = nfsva.na_mntonfileno;
 				    else
 					dp->d_fileno = nfsva.na_fileid;
 				} else if (nfsva.na_filesid[0] ==
 				    dnp->n_vattr.na_filesid[0] &&
 				    nfsva.na_filesid[1] ==
 				    dnp->n_vattr.na_filesid[1]) {
 				    dp->d_fileno = nfsva.na_fileid;
 				} else {
 				    do {
 					fakefileno--;
 				    } while (fakefileno ==
 					nfsva.na_fileid);
 				    dp->d_fileno = fakefileno;
 				}
 			    } else {
 				dp->d_fileno = fileno;
 			    }
 			    *tl2++ = cookiep->nfsuquad[0] = cookie.lval[0] =
 				ncookie.lval[0];
 			    *tl2 = cookiep->nfsuquad[1] = cookie.lval[1] =
 				ncookie.lval[1];
 
 			    if (nfhp != NULL) {
 				attr_ok = true;
 				if (NFSRV_CMPFH(nfhp->nfh_fh, nfhp->nfh_len,
 				    dnp->n_fhp->nfh_fh, dnp->n_fhp->nfh_len)) {
 				    VREF(vp);
 				    newvp = vp;
 				    unlocknewvp = 0;
 				    free(nfhp, M_NFSFH);
 				    np = dnp;
 				} else if (isdotdot != 0) {
 				    /*
 				     * Skip doing a nfscl_nget() call for "..".
 				     * There's a race between acquiring the nfs
 				     * node here and lookups that look for the
 				     * directory being read (in the parent).
 				     * It would try to get a lock on ".." here,
 				     * owning the lock on the directory being
 				     * read. Lookup will hold the lock on ".."
 				     * and try to acquire the lock on the
 				     * directory being read.
 				     * If the directory is unlocked/relocked,
 				     * then there is a LOR with the buflock
 				     * vp is relocked.
 				     */
 				    free(nfhp, M_NFSFH);
 				} else {
 				    error = nfscl_nget(vp->v_mount, vp,
 				      nfhp, cnp, p, &np, LK_EXCLUSIVE);
 				    if (!error) {
 					newvp = NFSTOV(np);
 					unlocknewvp = 1;
 					/*
 					 * If n_localmodtime >= time before RPC,
 					 * then a file modification operation,
 					 * such as VOP_SETATTR() of size, has
 					 * occurred while the Lookup RPC and
 					 * acquisition of the vnode happened. As
 					 * such, the attributes might be stale,
 					 * with possibly an incorrect size.
 					 */
 					NFSLOCKNODE(np);
 					if (timespecisset(
 					    &np->n_localmodtime) &&
 					    timespeccmp(&np->n_localmodtime,
 					    &ts, >=)) {
 					    NFSCL_DEBUG(4, "nfsrpc_readdirplus:"
 						" localmod stale attributes\n");
 					    attr_ok = false;
 					}
 					NFSUNLOCKNODE(np);
 				    }
 				}
 				nfhp = NULL;
 				if (newvp != NULLVP) {
 				    if (attr_ok)
 					error = nfscl_loadattrcache(&newvp,
 					    &nfsva, NULL, 0, 0);
 				    if (error) {
 					if (unlocknewvp)
 					    vput(newvp);
 					else
 					    vrele(newvp);
 					goto nfsmout;
 				    }
 				    dp->d_type =
 					vtonfs_dtype(np->n_vattr.na_type);
 				    ndp->ni_vp = newvp;
 				    NFSCNHASH(cnp, HASHINIT);
 				    if (cnp->cn_namelen <= NCHNAMLEN &&
 					ndp->ni_dvp != ndp->ni_vp &&
 					(newvp->v_type != VDIR ||
 					 dctime.tv_sec != 0)) {
 					cache_enter_time_flags(ndp->ni_dvp,
 					    ndp->ni_vp, cnp,
 					    &nfsva.na_ctime,
 					    newvp->v_type != VDIR ? NULL :
 					    &dctime, VFS_CACHE_DROPOLD);
 				    }
 				    if (unlocknewvp)
 					vput(newvp);
 				    else
 					vrele(newvp);
 				    newvp = NULLVP;
 				}
 			    }
 			} else if (nfhp != NULL) {
 			    free(nfhp, M_NFSFH);
 			}
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			more_dirs = fxdr_unsigned(int, *tl);
 		}
 		/*
 		 * If at end of rpc data, get the eof boolean
 		 */
 		if (!more_dirs) {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			eof = fxdr_unsigned(int, *tl);
 			if (tryformoredirs)
 				more_dirs = !eof;
 			if (nd->nd_flag & ND_NFSV4) {
 				error = nfscl_postop_attr(nd, nap, attrflagp);
 				if (error)
 					goto nfsmout;
 			}
 		}
 		m_freem(nd->nd_mrep);
 		nd->nd_mrep = NULL;
 	}
 	/*
 	 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 	 * by increasing d_reclen for the last record.
 	 */
 	if (blksiz > 0) {
 		left = DIRBLKSIZ - blksiz;
 		NFSBZERO(uiop->uio_iov->iov_base, left);
 		dp->d_reclen += left;
 		uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
 		    left;
 		uiop->uio_iov->iov_len -= left;
 		uiop->uio_resid -= left;
 		uiop->uio_offset += left;
 	}
 
 	/*
 	 * If returning no data, assume end of file.
 	 * If not bigenough, return not end of file, since you aren't
 	 *    returning all the data
 	 * Otherwise, return the eof flag from the server.
 	 */
 	if (eofp != NULL) {
 		if (tresid == uiop->uio_resid)
 			*eofp = 1;
 		else if (!bigenough)
 			*eofp = 0;
 		else
 			*eofp = eof;
 	}
 
 	/*
 	 * Add extra empty records to any remaining DIRBLKSIZ chunks.
 	 */
 	while (uiop->uio_resid > 0 && uiop->uio_resid != tresid) {
 		dp = (struct dirent *)uiop->uio_iov->iov_base;
 		NFSBZERO(dp, DIRBLKSIZ);
 		dp->d_type = DT_UNKNOWN;
 		tl = (u_int32_t *)&dp->d_name[4];
 		*tl++ = cookie.lval[0];
 		*tl = cookie.lval[1];
 		dp->d_reclen = DIRBLKSIZ;
 		uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
 		    DIRBLKSIZ;
 		uiop->uio_iov->iov_len -= DIRBLKSIZ;
 		uiop->uio_resid -= DIRBLKSIZ;
 		uiop->uio_offset += DIRBLKSIZ;
 	}
 
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Nfs commit rpc
  */
 int
 nfsrpc_commit(vnode_t vp, u_quad_t offset, int cnt, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	int error;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_COMMIT, vp, cred);
 	NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 	txdr_hyper(offset, tl);
 	tl += 2;
 	*tl = txdr_unsigned(cnt);
 	if (nd->nd_flag & ND_NFSV4) {
 		/*
 		 * And do a Getattr op.
 		 */
 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(NFSV4OP_GETATTR);
 		NFSGETATTR_ATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 	}
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	error = nfscl_wcc_data(nd, vp, nap, attrflagp, NULL, NULL);
 	if (!error && !nd->nd_repstat) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 		NFSLOCKMNT(nmp);
 		if (NFSBCMP(nmp->nm_verf, tl, NFSX_VERF)) {
 			NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 			nd->nd_repstat = NFSERR_STALEWRITEVERF;
 		}
 		NFSUNLOCKMNT(nmp);
 		if (nd->nd_flag & ND_NFSV4)
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 	}
 nfsmout:
 	if (!error && nd->nd_repstat)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * NFS byte range lock rpc.
  * (Mostly just calls one of the three lower level RPC routines.)
  */
 int
 nfsrpc_advlock(vnode_t vp, off_t size, int op, struct flock *fl,
     int reclaim, struct ucred *cred, NFSPROC_T *p, void *id, int flags)
 {
 	struct nfscllockowner *lp;
 	struct nfsclclient *clp;
 	struct nfsfh *nfhp;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	u_int64_t off, len;
 	off_t start, end;
 	u_int32_t clidrev = 0;
 	int error = 0, newone = 0, expireret = 0, retrycnt, donelocally;
 	int callcnt, dorpc;
 
 	/*
 	 * Convert the flock structure into a start and end and do POSIX
 	 * bounds checking.
 	 */
 	switch (fl->l_whence) {
 	case SEEK_SET:
 	case SEEK_CUR:
 		/*
 		 * Caller is responsible for adding any necessary offset
 		 * when SEEK_CUR is used.
 		 */
 		start = fl->l_start;
 		off = fl->l_start;
 		break;
 	case SEEK_END:
 		start = size + fl->l_start;
 		off = size + fl->l_start;
 		break;
 	default:
 		return (EINVAL);
 	}
 	if (start < 0)
 		return (EINVAL);
 	if (fl->l_len != 0) {
 		end = start + fl->l_len - 1;
 		if (end < start)
 			return (EINVAL);
 	}
 
 	len = fl->l_len;
 	if (len == 0)
 		len = NFS64BITSSET;
 	retrycnt = 0;
 	do {
 	    nd->nd_repstat = 0;
 	    if (op == F_GETLK) {
 		error = nfscl_getcl(vp->v_mount, cred, p, false, true, &clp);
 		if (error)
 			return (error);
 		error = nfscl_lockt(vp, clp, off, len, fl, p, id, flags);
 		if (!error) {
 			clidrev = clp->nfsc_clientidrev;
 			error = nfsrpc_lockt(nd, vp, clp, off, len, fl, cred,
 			    p, id, flags);
 		} else if (error == -1) {
 			error = 0;
 		}
 		nfscl_clientrelease(clp);
 	    } else if (op == F_UNLCK && fl->l_type == F_UNLCK) {
 		/*
 		 * We must loop around for all lockowner cases.
 		 */
 		callcnt = 0;
 		error = nfscl_getcl(vp->v_mount, cred, p, false, true, &clp);
 		if (error)
 			return (error);
 		do {
 		    error = nfscl_relbytelock(vp, off, len, cred, p, callcnt,
 			clp, id, flags, &lp, &dorpc);
 		    /*
 		     * If it returns a NULL lp, we're done.
 		     */
 		    if (lp == NULL) {
 			if (callcnt == 0)
 			    nfscl_clientrelease(clp);
 			else
 			    nfscl_releasealllocks(clp, vp, p, id, flags);
 			return (error);
 		    }
 		    if (nmp->nm_clp != NULL)
 			clidrev = nmp->nm_clp->nfsc_clientidrev;
 		    else
 			clidrev = 0;
 		    /*
 		     * If the server doesn't support Posix lock semantics,
 		     * only allow locks on the entire file, since it won't
 		     * handle overlapping byte ranges.
 		     * There might still be a problem when a lock
 		     * upgrade/downgrade (read<->write) occurs, since the
 		     * server "might" expect an unlock first?
 		     */
 		    if (dorpc && (lp->nfsl_open->nfso_posixlock ||
 			(off == 0 && len == NFS64BITSSET))) {
 			/*
 			 * Since the lock records will go away, we must
 			 * wait for grace and delay here.
 			 */
 			do {
 			    error = nfsrpc_locku(nd, nmp, lp, off, len,
 				NFSV4LOCKT_READ, cred, p, 0);
 			    if ((nd->nd_repstat == NFSERR_GRACE ||
 				 nd->nd_repstat == NFSERR_DELAY) &&
 				error == 0)
 				(void) nfs_catnap(PZERO, (int)nd->nd_repstat,
 				    "nfs_advlock");
 			} while ((nd->nd_repstat == NFSERR_GRACE ||
 			    nd->nd_repstat == NFSERR_DELAY) && error == 0);
 		    }
 		    callcnt++;
 		} while (error == 0 && nd->nd_repstat == 0);
 		nfscl_releasealllocks(clp, vp, p, id, flags);
 	    } else if (op == F_SETLK) {
 		error = nfscl_getbytelock(vp, off, len, fl->l_type, cred, p,
 		    NULL, 0, id, flags, NULL, NULL, &lp, &newone, &donelocally);
 		if (error || donelocally) {
 			return (error);
 		}
 		if (nmp->nm_clp != NULL)
 			clidrev = nmp->nm_clp->nfsc_clientidrev;
 		else
 			clidrev = 0;
 		nfhp = VTONFS(vp)->n_fhp;
 		if (!lp->nfsl_open->nfso_posixlock &&
 		    (off != 0 || len != NFS64BITSSET)) {
 			error = EINVAL;
 		} else {
 			error = nfsrpc_lock(nd, nmp, vp, nfhp->nfh_fh,
 			    nfhp->nfh_len, lp, newone, reclaim, off,
 			    len, fl->l_type, cred, p, 0);
 		}
 		if (!error)
 			error = nd->nd_repstat;
 		nfscl_lockrelease(lp, error, newone);
 	    } else {
 		error = EINVAL;
 	    }
 	    if (!error)
 	        error = nd->nd_repstat;
 	    if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		error == NFSERR_STALEDONTRECOVER ||
 		error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
 		error == NFSERR_BADSESSION) {
 		(void) nfs_catnap(PZERO, error, "nfs_advlock");
 	    } else if ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID)
 		&& clidrev != 0) {
 		expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		retrycnt++;
 	    }
 	} while (error == NFSERR_GRACE ||
 	    error == NFSERR_STALECLIENTID || error == NFSERR_DELAY ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_BADSESSION ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 /*
  * The lower level routine for the LockT case.
  */
 int
 nfsrpc_lockt(struct nfsrv_descript *nd, vnode_t vp,
     struct nfsclclient *clp, u_int64_t off, u_int64_t len, struct flock *fl,
     struct ucred *cred, NFSPROC_T *p, void *id, int flags)
 {
 	u_int32_t *tl;
 	int error, type, size;
 	uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 	struct nfsnode *np;
 	struct nfsmount *nmp;
 	struct nfsclsession *tsep;
 
 	nmp = VFSTONFS(vp->v_mount);
 	NFSCL_REQSTART(nd, NFSPROC_LOCKT, vp, cred);
 	NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 	if (fl->l_type == F_RDLCK)
 		*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 	else
 		*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 	txdr_hyper(off, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	tl += 2;
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	nfscl_filllockowner(id, own, flags);
 	np = VTONFS(vp);
 	NFSBCOPY(np->n_fhp->nfh_fh, &own[NFSV4CL_LOCKNAMELEN],
 	    np->n_fhp->nfh_len);
 	(void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + np->n_fhp->nfh_len);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		fl->l_type = F_UNLCK;
 	} else if (nd->nd_repstat == NFSERR_DENIED) {
 		nd->nd_repstat = 0;
 		fl->l_whence = SEEK_SET;
 		NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 		fl->l_start = fxdr_hyper(tl);
 		tl += 2;
 		len = fxdr_hyper(tl);
 		tl += 2;
 		if (len == NFS64BITSSET)
 			fl->l_len = 0;
 		else
 			fl->l_len = len;
 		type = fxdr_unsigned(int, *tl++);
 		if (type == NFSV4LOCKT_WRITE)
 			fl->l_type = F_WRLCK;
 		else
 			fl->l_type = F_RDLCK;
 		/*
 		 * XXX For now, I have no idea what to do with the
 		 * conflicting lock_owner, so I'll just set the pid == 0
 		 * and skip over the lock_owner.
 		 */
 		fl->l_pid = (pid_t)0;
 		tl += 2;
 		size = fxdr_unsigned(int, *tl);
 		if (size < 0 || size > NFSV4_OPAQUELIMIT)
 			error = EBADRPC;
 		if (!error)
 			error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
 	} else if (nd->nd_repstat == NFSERR_STALECLIENTID)
 		nfscl_initiate_recovery(clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Lower level function that performs the LockU RPC.
  */
 static int
 nfsrpc_locku(struct nfsrv_descript *nd, struct nfsmount *nmp,
     struct nfscllockowner *lp, u_int64_t off, u_int64_t len,
     u_int32_t type, struct ucred *cred, NFSPROC_T *p, int syscred)
 {
 	u_int32_t *tl;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LOCKU, nmp, lp->nfsl_open->nfso_fh,
 	    lp->nfsl_open->nfso_fhlen, NULL, NULL, 0, 0, cred);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(type);
 	*tl = txdr_unsigned(lp->nfsl_seqid);
 	if (nfstest_outofseq &&
 	    (arc4random() % nfstest_outofseq) == 0)
 		*tl = txdr_unsigned(lp->nfsl_seqid + 1);
 	tl++;
 	if (NFSHASNFSV4N(nmp))
 		*tl++ = 0;
 	else
 		*tl++ = lp->nfsl_stateid.seqid;
 	*tl++ = lp->nfsl_stateid.other[0];
 	*tl++ = lp->nfsl_stateid.other[1];
 	*tl++ = lp->nfsl_stateid.other[2];
 	txdr_hyper(off, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	NFSCL_INCRSEQID(lp->nfsl_seqid, nd);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 		lp->nfsl_stateid.seqid = *tl++;
 		lp->nfsl_stateid.other[0] = *tl++;
 		lp->nfsl_stateid.other[1] = *tl++;
 		lp->nfsl_stateid.other[2] = *tl;
 	} else if (nd->nd_repstat == NFSERR_STALESTATEID)
 		nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The actual Lock RPC.
  */
 int
 nfsrpc_lock(struct nfsrv_descript *nd, struct nfsmount *nmp, vnode_t vp,
     u_int8_t *nfhp, int fhlen, struct nfscllockowner *lp, int newone,
     int reclaim, u_int64_t off, u_int64_t len, short type, struct ucred *cred,
     NFSPROC_T *p, int syscred)
 {
 	u_int32_t *tl;
 	int error, size;
 	uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 	struct nfsclsession *tsep;
 
 	nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL, NULL, 0, 0,
 	    cred);
 	NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 	if (type == F_RDLCK)
 		*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
 	else
 		*tl++ = txdr_unsigned(NFSV4LOCKT_WRITE);
 	*tl++ = txdr_unsigned(reclaim);
 	txdr_hyper(off, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	tl += 2;
 	if (newone) {
 	    *tl = newnfs_true;
 	    NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID +
 		2 * NFSX_UNSIGNED + NFSX_HYPER);
 	    *tl++ = txdr_unsigned(lp->nfsl_open->nfso_own->nfsow_seqid);
 	    if (NFSHASNFSV4N(nmp))
 		*tl++ = 0;
 	    else
 		*tl++ = lp->nfsl_open->nfso_stateid.seqid;
 	    *tl++ = lp->nfsl_open->nfso_stateid.other[0];
 	    *tl++ = lp->nfsl_open->nfso_stateid.other[1];
 	    *tl++ = lp->nfsl_open->nfso_stateid.other[2];
 	    *tl++ = txdr_unsigned(lp->nfsl_seqid);
 	    tsep = nfsmnt_mdssession(nmp);
 	    *tl++ = tsep->nfsess_clientid.lval[0];
 	    *tl = tsep->nfsess_clientid.lval[1];
 	    NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 	    NFSBCOPY(nfhp, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 	    (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
 	} else {
 	    *tl = newnfs_false;
 	    NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
 	    if (NFSHASNFSV4N(nmp))
 		*tl++ = 0;
 	    else
 		*tl++ = lp->nfsl_stateid.seqid;
 	    *tl++ = lp->nfsl_stateid.other[0];
 	    *tl++ = lp->nfsl_stateid.other[1];
 	    *tl++ = lp->nfsl_stateid.other[2];
 	    *tl = txdr_unsigned(lp->nfsl_seqid);
 	    if (nfstest_outofseq &&
 		(arc4random() % nfstest_outofseq) == 0)
 		    *tl = txdr_unsigned(lp->nfsl_seqid + 1);
 	}
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	if (newone)
 	    NFSCL_INCRSEQID(lp->nfsl_open->nfso_own->nfsow_seqid, nd);
 	NFSCL_INCRSEQID(lp->nfsl_seqid, nd);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID);
 		lp->nfsl_stateid.seqid = *tl++;
 		lp->nfsl_stateid.other[0] = *tl++;
 		lp->nfsl_stateid.other[1] = *tl++;
 		lp->nfsl_stateid.other[2] = *tl;
 	} else if (nd->nd_repstat == NFSERR_DENIED) {
 		NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 		size = fxdr_unsigned(int, *(tl + 7));
 		if (size < 0 || size > NFSV4_OPAQUELIMIT)
 			error = EBADRPC;
 		if (!error)
 			error = nfsm_advance(nd, NFSM_RNDUP(size), -1);
 	} else if (nd->nd_repstat == NFSERR_STALESTATEID)
 		nfscl_initiate_recovery(lp->nfsl_open->nfso_own->nfsow_clp);
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs statfs rpc
  * (always called with the vp for the mount point)
  */
 int
 nfsrpc_statfs(vnode_t vp, struct nfsstatfs *sbp, struct nfsfsinfo *fsp,
     uint32_t *leasep, struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap,
     int *attrflagp)
 {
 	u_int32_t *tl = NULL;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	nfsattrbit_t attrbits;
 	int error;
 
 	*attrflagp = 0;
 	nmp = VFSTONFS(vp->v_mount);
 	if (NFSHASNFSV4(nmp)) {
 		/*
 		 * For V4, you actually do a getattr.
 		 */
 		NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp, cred);
 		if (leasep != NULL)
 			NFSROOTFS_GETATTRBIT(&attrbits);
 		else
 			NFSSTATFS_GETATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		nd->nd_flag |= ND_USEGSSNAME;
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (nd->nd_repstat == 0) {
 			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 			    NULL, NULL, sbp, fsp, NULL, 0, NULL, leasep, NULL,
 			    p, cred);
 			if (!error) {
 				nmp->nm_fsid[0] = nap->na_filesid[0];
 				nmp->nm_fsid[1] = nap->na_filesid[1];
 				NFSSETHASSETFSID(nmp);
 				*attrflagp = 1;
 			}
 		} else {
 			error = nd->nd_repstat;
 		}
 		if (error)
 			goto nfsmout;
 	} else {
 		NFSCL_REQSTART(nd, NFSPROC_FSSTAT, vp, NULL);
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (nd->nd_flag & ND_NFSV3) {
 			error = nfscl_postop_attr(nd, nap, attrflagp);
 			if (error)
 				goto nfsmout;
 		}
 		if (nd->nd_repstat) {
 			error = nd->nd_repstat;
 			goto nfsmout;
 		}
 		NFSM_DISSECT(tl, u_int32_t *,
 		    NFSX_STATFS(nd->nd_flag & ND_NFSV3));
 	}
 	if (NFSHASNFSV3(nmp)) {
 		sbp->sf_tbytes = fxdr_hyper(tl); tl += 2;
 		sbp->sf_fbytes = fxdr_hyper(tl); tl += 2;
 		sbp->sf_abytes = fxdr_hyper(tl); tl += 2;
 		sbp->sf_tfiles = fxdr_hyper(tl); tl += 2;
 		sbp->sf_ffiles = fxdr_hyper(tl); tl += 2;
 		sbp->sf_afiles = fxdr_hyper(tl); tl += 2;
 		sbp->sf_invarsec = fxdr_unsigned(u_int32_t, *tl);
 	} else if (NFSHASNFSV4(nmp) == 0) {
 		sbp->sf_tsize = fxdr_unsigned(u_int32_t, *tl++);
 		sbp->sf_bsize = fxdr_unsigned(u_int32_t, *tl++);
 		sbp->sf_blocks = fxdr_unsigned(u_int32_t, *tl++);
 		sbp->sf_bfree = fxdr_unsigned(u_int32_t, *tl++);
 		sbp->sf_bavail = fxdr_unsigned(u_int32_t, *tl);
 	}
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs pathconf rpc
  */
 int
 nfsrpc_pathconf(vnode_t vp, struct nfsv3_pathconf *pc,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp;
 	u_int32_t *tl;
 	nfsattrbit_t attrbits;
 	int error;
 	struct nfsnode *np;
 
 	*attrflagp = 0;
 	nmp = VFSTONFS(vp->v_mount);
 	if (NFSHASNFSV4(nmp)) {
 		np = VTONFS(vp);
 		if ((nmp->nm_privflag & NFSMNTP_FAKEROOTFH) != 0 &&
 		    nmp->nm_fhsize == 0) {
 			/* Attempt to get the actual root file handle. */
 			error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
 			    cred, p);
 			if (error != 0)
 				return (EACCES);
 			if (np->n_fhp->nfh_len == NFSX_FHMAX + 1)
 				nfscl_statfs(vp, cred, p);
 		}
 		/*
 		 * For V4, you actually do a getattr.
 		 */
 		NFSCL_REQSTART(nd, NFSPROC_GETATTR, vp, cred);
 		NFSPATHCONF_GETATTRBIT(&attrbits);
 		(void) nfsrv_putattrbit(nd, &attrbits);
 		nd->nd_flag |= ND_USEGSSNAME;
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		if (nd->nd_repstat == 0) {
 			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
 			    pc, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, p,
 			    cred);
 			if (!error)
 				*attrflagp = 1;
 		} else {
 			error = nd->nd_repstat;
 		}
 	} else {
 		NFSCL_REQSTART(nd, NFSPROC_PATHCONF, vp, NULL);
 		error = nfscl_request(nd, vp, p, cred);
 		if (error)
 			return (error);
 		error = nfscl_postop_attr(nd, nap, attrflagp);
 		if (nd->nd_repstat && !error)
 			error = nd->nd_repstat;
 		if (!error) {
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V3PATHCONF);
 			pc->pc_linkmax = fxdr_unsigned(u_int32_t, *tl++);
 			pc->pc_namemax = fxdr_unsigned(u_int32_t, *tl++);
 			pc->pc_notrunc = fxdr_unsigned(u_int32_t, *tl++);
 			pc->pc_chownrestricted =
 			    fxdr_unsigned(u_int32_t, *tl++);
 			pc->pc_caseinsensitive =
 			    fxdr_unsigned(u_int32_t, *tl++);
 			pc->pc_casepreserving = fxdr_unsigned(u_int32_t, *tl);
 		}
 	}
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs version 3 fsinfo rpc call
  */
 int
 nfsrpc_fsinfo(vnode_t vp, struct nfsfsinfo *fsp, struct ucred *cred,
     NFSPROC_T *p, struct nfsvattr *nap, int *attrflagp)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_FSINFO, vp, NULL);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	error = nfscl_postop_attr(nd, nap, attrflagp);
 	if (nd->nd_repstat && !error)
 		error = nd->nd_repstat;
 	if (!error) {
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_V3FSINFO);
 		fsp->fs_rtmax = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_rtpref = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_rtmult = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_wtmax = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_wtpref = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_wtmult = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_dtpref = fxdr_unsigned(u_int32_t, *tl++);
 		fsp->fs_maxfilesize = fxdr_hyper(tl);
 		tl += 2;
 		fxdr_nfsv3time(tl, &fsp->fs_timedelta);
 		tl += 2;
 		fsp->fs_properties = fxdr_unsigned(u_int32_t, *tl);
 	}
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * This function performs the Renew RPC.
  */
 int
 nfsrpc_renew(struct nfsclclient *clp, struct nfsclds *dsp, struct ucred *cred,
     NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfsmount *nmp;
 	int error;
 	struct nfssockreq *nrp;
 	struct nfsclsession *tsep;
 
 	nmp = clp->nfsc_nmp;
 	if (nmp == NULL)
 		return (0);
 	if (dsp == NULL)
 		nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL, 0,
 		    0, cred);
 	else
 		nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
 		    &dsp->nfsclds_sess, 0, 0, NULL);
 	if (!NFSHASNFSV4N(nmp)) {
 		/* NFSv4.1 just uses a Sequence Op and not a Renew. */
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		tsep = nfsmnt_mdssession(nmp);
 		*tl++ = tsep->nfsess_clientid.lval[0];
 		*tl = tsep->nfsess_clientid.lval[1];
 	}
 	nrp = NULL;
 	if (dsp != NULL)
 		nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	nd->nd_flag |= ND_USEGSSNAME;
 	if (dsp == NULL)
 		error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 		    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	else {
 		error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 		    NFS_PROG, NFS_VER4, NULL, 1, NULL, &dsp->nfsclds_sess);
 		if (error == ENXIO)
 			nfscl_cancelreqs(dsp);
 	}
 	if (error)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * This function performs the Releaselockowner RPC.
  */
 int
 nfsrpc_rellockown(struct nfsmount *nmp, struct nfscllockowner *lp,
     uint8_t *fh, int fhlen, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	u_int32_t *tl;
 	int error;
 	uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 	struct nfsclsession *tsep;
 
 	if (NFSHASNFSV4N(nmp)) {
 		/* For NFSv4.1, do a FreeStateID. */
 		nfscl_reqstart(nd, NFSPROC_FREESTATEID, nmp, NULL, 0, NULL,
 		    NULL, 0, 0, cred);
 		nfsm_stateidtom(nd, &lp->nfsl_stateid, NFSSTATEID_PUTSTATEID);
 	} else {
 		nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL,
 		    NULL, 0, 0, NULL);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		tsep = nfsmnt_mdssession(nmp);
 		*tl++ = tsep->nfsess_clientid.lval[0];
 		*tl = tsep->nfsess_clientid.lval[1];
 		NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
 		NFSBCOPY(fh, &own[NFSV4CL_LOCKNAMELEN], fhlen);
 		(void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
 	}
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * This function performs the Compound to get the mount pt FH.
  */
 int
 nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpath, struct ucred *cred,
     NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	u_char *cp, *cp2, *fhp;
 	int error, cnt, len, setnil;
 	u_int32_t *opcntp;
 
 	nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL, 0,
 	    0, NULL);
 	cp = dirpath;
 	cnt = 0;
 	do {
 		setnil = 0;
 		while (*cp == '/')
 			cp++;
 		cp2 = cp;
 		while (*cp2 != '\0' && *cp2 != '/')
 			cp2++;
 		if (*cp2 == '/') {
 			setnil = 1;
 			*cp2 = '\0';
 		}
 		if (cp2 != cp) {
 			NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 			*tl = txdr_unsigned(NFSV4OP_LOOKUP);
 			nfsm_strtom(nd, cp, strlen(cp));
 			cnt++;
 		}
 		if (setnil)
 			*cp2++ = '/';
 		cp = cp2;
 	} while (*cp != '\0');
 	if (NFSHASNFSV4N(nmp))
 		/* Has a Sequence Op done by nfscl_reqstart(). */
 		*opcntp = txdr_unsigned(3 + cnt);
 	else
 		*opcntp = txdr_unsigned(2 + cnt);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETFH);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 		NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, (3 + 2 * cnt) * NFSX_UNSIGNED);
 		tl += (2 + 2 * cnt);
 		if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
 			len > NFSX_FHMAX) {
 			nd->nd_repstat = NFSERR_BADXDR;
 		} else {
 			fhp = malloc(len + 1, M_TEMP, M_WAITOK);
 			nd->nd_repstat = nfsrv_mtostr(nd, fhp, len);
 			if (nd->nd_repstat == 0) {
 				NFSLOCKMNT(nmp);
 				if (nmp->nm_fhsize == 0) {
 					NFSBCOPY(fhp, nmp->nm_fh, len);
 					nmp->nm_fhsize = len;
 				}
 				NFSUNLOCKMNT(nmp);
 			}
 			free(fhp, M_TEMP);
 		}
 	}
 	error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * This function performs the Delegreturn RPC.
  */
 int
 nfsrpc_delegreturn(struct nfscldeleg *dp, struct ucred *cred,
     struct nfsmount *nmp, NFSPROC_T *p, int syscred)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_DELEGRETURN, nmp, dp->nfsdl_fh,
 	    dp->nfsdl_fhlen, NULL, NULL, 0, 0, cred);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 	if (NFSHASNFSV4N(nmp))
 		*tl++ = 0;
 	else
 		*tl++ = dp->nfsdl_stateid.seqid;
 	*tl++ = dp->nfsdl_stateid.other[0];
 	*tl++ = dp->nfsdl_stateid.other[1];
 	*tl = dp->nfsdl_stateid.other[2];
 	if (syscred)
 		nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs getacl call.
  */
 int
 nfsrpc_getacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 	nfsattrbit_t attrbits;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 
 	if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp))
 		return (EOPNOTSUPP);
 	NFSCL_REQSTART(nd, NFSPROC_GETACL, vp, cred);
 	NFSZERO_ATTRBIT(&attrbits);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
 	(void) nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	if (!nd->nd_repstat)
 		error = nfsv4_loadattr(nd, vp, NULL, NULL, NULL, 0, NULL,
 		    NULL, NULL, NULL, aclp, 0, NULL, NULL, NULL, p, cred);
 	else
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * nfs setacl call.
  */
 int
 nfsrpc_setacl(vnode_t vp, struct ucred *cred, NFSPROC_T *p, struct acl *aclp)
 {
 	int error;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 
 	if (nfsrv_useacl == 0 || !NFSHASNFSV4(nmp))
 		return (EOPNOTSUPP);
 	error = nfsrpc_setattr(vp, NULL, aclp, cred, p, NULL, NULL);
 	return (error);
 }
 
 /*
  * nfs setacl call.
  */
 static int
 nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
     struct acl *aclp, nfsv4stateid_t *stateidp)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 	nfsattrbit_t attrbits;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 
 	if (!NFSHASNFSV4(nmp))
 		return (EOPNOTSUPP);
 	NFSCL_REQSTART(nd, NFSPROC_SETACL, vp, cred);
 	nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 	NFSZERO_ATTRBIT(&attrbits);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
 	(void) nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0,
 	    &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error)
 		return (error);
 	/* Don't care about the pre/postop attributes */
 	m_freem(nd->nd_mrep);
 	return (nd->nd_repstat);
 }
 
 /*
  * Do the NFSv4.1 Exchange ID.
  */
 int
 nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclclient *clp,
     struct nfssockreq *nrp, int minorvers, uint32_t exchflags,
     struct nfsclds **dspp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl, v41flags;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfsclds *dsp;
 	struct timespec verstime;
 	int error, len;
 
 	*dspp = NULL;
 	if (minorvers == 0)
 		minorvers = nmp->nm_minorvers;
 	nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL,
 	    NFS_VER4, minorvers, NULL);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec);	/* Client owner */
 	*tl = txdr_unsigned(clp->nfsc_rev);
 	(void) nfsm_strtom(nd, clp->nfsc_id, clp->nfsc_idlen);
 
 	NFSM_BUILD(tl, uint32_t *, 3 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(exchflags);
 	*tl++ = txdr_unsigned(NFSV4EXCH_SP4NONE);
 
 	/* Set the implementation id4 */
 	*tl = txdr_unsigned(1);
 	(void) nfsm_strtom(nd, "freebsd.org", strlen("freebsd.org"));
 	(void) nfsm_strtom(nd, version, strlen(version));
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4TIME);
 	verstime.tv_sec = 1293840000;		/* Jan 1, 2011 */
 	verstime.tv_nsec = 0;
 	txdr_nfsv4time(&verstime, tl);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	NFSCL_DEBUG(1, "exchangeid err=%d reps=%d\n", error,
 	    (int)nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 6 * NFSX_UNSIGNED + NFSX_HYPER);
 		len = fxdr_unsigned(int, *(tl + 7));
 		if (len < 0 || len > NFSV4_OPAQUELIMIT) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		dsp = malloc(sizeof(struct nfsclds) + len + 1, M_NFSCLDS,
 		    M_WAITOK | M_ZERO);
 		dsp->nfsclds_expire = NFSD_MONOSEC + clp->nfsc_renew;
 		dsp->nfsclds_servownlen = len;
 		dsp->nfsclds_sess.nfsess_clientid.lval[0] = *tl++;
 		dsp->nfsclds_sess.nfsess_clientid.lval[1] = *tl++;
 		dsp->nfsclds_sess.nfsess_sequenceid =
 		    fxdr_unsigned(uint32_t, *tl++);
 		v41flags = fxdr_unsigned(uint32_t, *tl);
 		if ((v41flags & NFSV4EXCH_USEPNFSMDS) != 0 &&
 		    NFSHASPNFSOPT(nmp)) {
 			NFSCL_DEBUG(1, "set PNFS\n");
 			NFSLOCKMNT(nmp);
 			nmp->nm_state |= NFSSTA_PNFS;
 			NFSUNLOCKMNT(nmp);
 			dsp->nfsclds_flags |= NFSCLDS_MDS;
 		}
 		if ((v41flags & NFSV4EXCH_USEPNFSDS) != 0)
 			dsp->nfsclds_flags |= NFSCLDS_DS;
 		if (minorvers == NFSV42_MINORVERSION)
 			dsp->nfsclds_flags |= NFSCLDS_MINORV2;
 		if (len > 0)
 			nd->nd_repstat = nfsrv_mtostr(nd,
 			    dsp->nfsclds_serverown, len);
 		if (nd->nd_repstat == 0) {
 			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 			mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
 			    NULL, MTX_DEF);
 			nfscl_initsessionslots(&dsp->nfsclds_sess);
 			*dspp = dsp;
 		} else
 			free(dsp, M_NFSCLDS);
 	}
 	error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 Create Session.
  */
 int
 nfsrpc_createsession(struct nfsmount *nmp, struct nfsclsession *sep,
     struct nfssockreq *nrp, struct nfsclds *dsp, uint32_t sequenceid, int mds,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t crflags, maxval, *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	int error, irdcnt, minorvers;
 
 	/* Make sure nm_rsize, nm_wsize is set. */
 	if (nmp->nm_rsize > NFS_MAXBSIZE || nmp->nm_rsize == 0)
 		nmp->nm_rsize = NFS_MAXBSIZE;
 	if (nmp->nm_wsize > NFS_MAXBSIZE || nmp->nm_wsize == 0)
 		nmp->nm_wsize = NFS_MAXBSIZE;
 	if (dsp == NULL)
 		minorvers = nmp->nm_minorvers;
 	else if ((dsp->nfsclds_flags & NFSCLDS_MINORV2) != 0)
 		minorvers = NFSV42_MINORVERSION;
 	else
 		minorvers = NFSV41_MINORVERSION;
 	nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL,
 	    NFS_VER4, minorvers, NULL);
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 	*tl++ = sep->nfsess_clientid.lval[0];
 	*tl++ = sep->nfsess_clientid.lval[1];
 	*tl++ = txdr_unsigned(sequenceid);
 	crflags = (NFSMNT_RDONLY(nmp->nm_mountp) ? 0 : NFSV4CRSESS_PERSIST);
 	if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0 && mds != 0)
 		crflags |= NFSV4CRSESS_CONNBACKCHAN;
 	*tl = txdr_unsigned(crflags);
 
 	/* Fill in fore channel attributes. */
 	NFSM_BUILD(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 	*tl++ = 0;				/* Header pad size */
 	if ((nd->nd_flag & ND_NFSV42) != 0 && mds != 0 && sb_max_adj >=
 	    nmp->nm_wsize && sb_max_adj >= nmp->nm_rsize) {
 		/*
 		 * NFSv4.2 Extended Attribute operations may want to do
 		 * requests/replies that are larger than nm_rsize/nm_wsize.
 		 */
 		*tl++ = txdr_unsigned(sb_max_adj - NFS_MAXXDR);
 		*tl++ = txdr_unsigned(sb_max_adj - NFS_MAXXDR);
 	} else {
 		*tl++ = txdr_unsigned(nmp->nm_wsize + NFS_MAXXDR);
 		*tl++ = txdr_unsigned(nmp->nm_rsize + NFS_MAXXDR);
 	}
 	*tl++ = txdr_unsigned(4096);		/* Max response size cached */
 	*tl++ = txdr_unsigned(20);		/* Max operations */
 	*tl++ = txdr_unsigned(64);		/* Max slots */
 	*tl = 0;				/* No rdma ird */
 
 	/* Fill in back channel attributes. */
 	NFSM_BUILD(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 	*tl++ = 0;				/* Header pad size */
 	*tl++ = txdr_unsigned(10000);		/* Max request size */
 	*tl++ = txdr_unsigned(10000);		/* Max response size */
 	*tl++ = txdr_unsigned(4096);		/* Max response size cached */
 	*tl++ = txdr_unsigned(4);		/* Max operations */
 	*tl++ = txdr_unsigned(NFSV4_CBSLOTS);	/* Max slots */
 	*tl = 0;				/* No rdma ird */
 
 	NFSM_BUILD(tl, uint32_t *, 8 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFS_CALLBCKPROG);	/* Call back prog # */
 
 	/* Allow AUTH_SYS callbacks as uid, gid == 0. */
 	*tl++ = txdr_unsigned(1);		/* Auth_sys only */
 	*tl++ = txdr_unsigned(AUTH_SYS);	/* AUTH_SYS type */
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec); /* time stamp */
 	*tl++ = 0;				/* Null machine name */
 	*tl++ = 0;				/* Uid == 0 */
 	*tl++ = 0;				/* Gid == 0 */
 	*tl = 0;				/* No additional gids */
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, nrp, NULL, p, cred, NFS_PROG,
 	    NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID +
 		    2 * NFSX_UNSIGNED);
 		bcopy(tl, sep->nfsess_sessionid, NFSX_V4SESSIONID);
 		tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
 		sep->nfsess_sequenceid = fxdr_unsigned(uint32_t, *tl++);
 		crflags = fxdr_unsigned(uint32_t, *tl);
 		if ((crflags & NFSV4CRSESS_PERSIST) != 0 && mds != 0) {
 			NFSLOCKMNT(nmp);
 			nmp->nm_state |= NFSSTA_SESSPERSIST;
 			NFSUNLOCKMNT(nmp);
 		}
 
 		/* Get the fore channel slot count. */
 		NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 		tl++;			/* Skip the header pad size. */
 
 		/* Make sure nm_wsize is small enough. */
 		maxval = fxdr_unsigned(uint32_t, *tl++);
 		while (maxval < nmp->nm_wsize + NFS_MAXXDR) {
 			if (nmp->nm_wsize > 8096)
 				nmp->nm_wsize /= 2;
 			else
 				break;
 		}
 		sep->nfsess_maxreq = maxval;
 
 		/* Make sure nm_rsize is small enough. */
 		maxval = fxdr_unsigned(uint32_t, *tl++);
 		while (maxval < nmp->nm_rsize + NFS_MAXXDR) {
 			if (nmp->nm_rsize > 8096)
 				nmp->nm_rsize /= 2;
 			else
 				break;
 		}
 		sep->nfsess_maxresp = maxval;
 
 		sep->nfsess_maxcache = fxdr_unsigned(int, *tl++);
 		tl++;
 		sep->nfsess_foreslots = fxdr_unsigned(uint16_t, *tl++);
 		NFSCL_DEBUG(4, "fore slots=%d\n", (int)sep->nfsess_foreslots);
 		irdcnt = fxdr_unsigned(int, *tl);
 		if (irdcnt < 0 || irdcnt > 1) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		if (irdcnt > 0)
 			NFSM_DISSECT(tl, uint32_t *, irdcnt * NFSX_UNSIGNED);
 
 		/* and the back channel slot count. */
 		NFSM_DISSECT(tl, uint32_t *, 7 * NFSX_UNSIGNED);
 		tl += 5;
 		sep->nfsess_backslots = fxdr_unsigned(uint16_t, *tl);
 		NFSCL_DEBUG(4, "back slots=%d\n", (int)sep->nfsess_backslots);
 	}
 	error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 Destroy Client.
  */
 int
 nfsrpc_destroyclient(struct nfsmount *nmp, struct nfsclclient *clp,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	int error;
 	struct nfsclsession *tsep;
 
 	nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL, 0,
 	    0, NULL);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 LayoutGet.
  */
 static int
 nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, int fhlen, int iomode,
     uint64_t offset, uint64_t len, uint64_t minlen, int layouttype,
     int layoutlen, nfsv4stateid_t *stateidp, int *retonclosep,
     struct nfsclflayouthead *flhp, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL, 0,
 	    0, cred);
 	nfsrv_setuplayoutget(nd, iomode, offset, len, minlen, stateidp,
 	    layouttype, layoutlen, 0);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	NFSCL_DEBUG(4, "layget err=%d st=%d\n", error, nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0)
 		error = nfsrv_parselayoutget(nmp, nd, stateidp, retonclosep,
 		    flhp);
 	if (error == 0 && nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 Get Device Info.
  */
 int
 nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
     uint32_t *notifybitsp, struct nfscldevinfo **ndip, struct ucred *cred,
     NFSPROC_T *p)
 {
 	uint32_t cnt, *tl, vers, minorvers;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct sockaddr_in sin, ssin;
 	struct sockaddr_in6 sin6, ssin6;
 	struct nfsclds *dsp = NULL, **dspp, **gotdspp;
 	struct nfscldevinfo *ndi;
 	int addrcnt = 0, bitcnt, error, gotminor, gotvers, i, isudp, j;
 	int stripecnt;
 	uint8_t stripeindex;
 	sa_family_t af, safilled;
 
 	ssin.sin_port = 0;		/* To shut up compiler. */
 	ssin.sin_addr.s_addr = 0;	/* ditto */
 	*ndip = NULL;
 	ndi = NULL;
 	gotdspp = NULL;
 	nfscl_reqstart(nd, NFSPROC_GETDEVICEINFO, nmp, NULL, 0, NULL, NULL, 0,
 	    0, cred);
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
 	NFSBCOPY(deviceid, tl, NFSX_V4DEVICEID);
 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(layouttype);
 	*tl++ = txdr_unsigned(100000);
 	if (notifybitsp != NULL && *notifybitsp != 0) {
 		*tl = txdr_unsigned(1);		/* One word of bits. */
 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(*notifybitsp);
 	} else
 		*tl = txdr_unsigned(0);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		if (layouttype != fxdr_unsigned(int, *tl))
 			printf("EEK! devinfo layout type not same!\n");
 		if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			stripecnt = fxdr_unsigned(int, *tl);
 			NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt);
 			if (stripecnt < 1 || stripecnt > 4096) {
 				printf("pNFS File layout devinfo stripecnt %d:"
 				    " out of range\n", stripecnt);
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 			NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) *
 			    NFSX_UNSIGNED);
 			addrcnt = fxdr_unsigned(int, *(tl + stripecnt));
 			NFSCL_DEBUG(4, "addrcnt=%d\n", addrcnt);
 			if (addrcnt < 1 || addrcnt > 128) {
 				printf("NFS devinfo addrcnt %d: out of range\n",
 				    addrcnt);
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 
 			/*
 			 * Now we know how many stripe indices and addresses, so
 			 * we can allocate the structure the correct size.
 			 */
 			i = (stripecnt * sizeof(uint8_t)) /
 			    sizeof(struct nfsclds *) + 1;
 			NFSCL_DEBUG(4, "stripeindices=%d\n", i);
 			ndi = malloc(sizeof(*ndi) + (addrcnt + i) *
 			    sizeof(struct nfsclds *), M_NFSDEVINFO, M_WAITOK |
 			    M_ZERO);
 			NFSBCOPY(deviceid, ndi->nfsdi_deviceid,
 			    NFSX_V4DEVICEID);
 			ndi->nfsdi_refcnt = 0;
 			ndi->nfsdi_flags = NFSDI_FILELAYOUT;
 			ndi->nfsdi_stripecnt = stripecnt;
 			ndi->nfsdi_addrcnt = addrcnt;
 			/* Fill in the stripe indices. */
 			for (i = 0; i < stripecnt; i++) {
 				stripeindex = fxdr_unsigned(uint8_t, *tl++);
 				NFSCL_DEBUG(4, "stripeind=%d\n", stripeindex);
 				if (stripeindex >= addrcnt) {
 					printf("pNFS File Layout devinfo"
 					    " stripeindex %d: too big\n",
 					    (int)stripeindex);
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 				nfsfldi_setstripeindex(ndi, i, stripeindex);
 			}
 		} else if (layouttype == NFSLAYOUT_FLEXFILE) {
 			/* For Flex File, we only get one address list. */
 			ndi = malloc(sizeof(*ndi) + sizeof(struct nfsclds *),
 			    M_NFSDEVINFO, M_WAITOK | M_ZERO);
 			NFSBCOPY(deviceid, ndi->nfsdi_deviceid,
 			    NFSX_V4DEVICEID);
 			ndi->nfsdi_refcnt = 0;
 			ndi->nfsdi_flags = NFSDI_FLEXFILE;
 			addrcnt = ndi->nfsdi_addrcnt = 1;
 		}
 
 		/* Now, dissect the server address(es). */
 		safilled = AF_UNSPEC;
 		for (i = 0; i < addrcnt; i++) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			cnt = fxdr_unsigned(uint32_t, *tl);
 			if (cnt == 0) {
 				printf("NFS devinfo 0 len addrlist\n");
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 			dspp = nfsfldi_addr(ndi, i);
 			safilled = AF_UNSPEC;
 			for (j = 0; j < cnt; j++) {
 				error = nfsv4_getipaddr(nd, &sin, &sin6, &af,
 				    &isudp);
 				if (error != 0 && error != EPERM) {
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 				if (error == 0 && isudp == 0) {
 					/*
 					 * The priority is:
 					 * - Same address family.
 					 * Save the address and dspp, so that
 					 * the connection can be done after
 					 * parsing is complete.
 					 */
 					if (safilled == AF_UNSPEC ||
 					    (af == nmp->nm_nam->sa_family &&
 					     safilled != nmp->nm_nam->sa_family)
 					   ) {
 						if (af == AF_INET)
 							ssin = sin;
 						else
 							ssin6 = sin6;
 						safilled = af;
 						gotdspp = dspp;
 					}
 				}
 			}
 		}
 
 		gotvers = NFS_VER4;	/* Default NFSv4.1 for File Layout. */
 		gotminor = NFSV41_MINORVERSION;
 		/* For Flex File, we will take one of the versions to use. */
 		if (layouttype == NFSLAYOUT_FLEXFILE) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			j = fxdr_unsigned(int, *tl);
 			if (j < 1 || j > NFSDEV_MAXVERS) {
 				printf("pNFS: too many versions\n");
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 			gotvers = 0;
 			gotminor = 0;
 			for (i = 0; i < j; i++) {
 				NFSM_DISSECT(tl, uint32_t *, 5 * NFSX_UNSIGNED);
 				vers = fxdr_unsigned(uint32_t, *tl++);
 				minorvers = fxdr_unsigned(uint32_t, *tl++);
 				if (vers == NFS_VER3)
 					minorvers = 0;
 				if ((vers == NFS_VER4 && ((minorvers ==
 				    NFSV41_MINORVERSION && gotminor == 0) ||
 				    minorvers == NFSV42_MINORVERSION)) ||
 				    (vers == NFS_VER3 && gotvers == 0)) {
 					gotvers = vers;
 					gotminor = minorvers;
 					/* We'll take this one. */
 					ndi->nfsdi_versindex = i;
 					ndi->nfsdi_vers = vers;
 					ndi->nfsdi_minorvers = minorvers;
 					ndi->nfsdi_rsize = fxdr_unsigned(
 					    uint32_t, *tl++);
 					ndi->nfsdi_wsize = fxdr_unsigned(
 					    uint32_t, *tl++);
 					if (*tl == newnfs_true)
 						ndi->nfsdi_flags |=
 						    NFSDI_TIGHTCOUPLED;
 					else
 						ndi->nfsdi_flags &=
 						    ~NFSDI_TIGHTCOUPLED;
 				}
 			}
 			if (gotvers == 0) {
 				printf("pNFS: no NFSv3, NFSv4.1 or NFSv4.2\n");
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 		}
 
 		/* And the notify bits. */
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		bitcnt = fxdr_unsigned(int, *tl);
 		if (bitcnt > 0) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			if (notifybitsp != NULL)
 				*notifybitsp =
 				    fxdr_unsigned(uint32_t, *tl);
 		}
 		if (safilled != AF_UNSPEC) {
 			KASSERT(ndi != NULL, ("ndi is NULL"));
 			*ndip = ndi;
 		} else
 			error = EPERM;
 		if (error == 0) {
 			/*
 			 * Now we can do a TCP connection for the correct
 			 * NFS version and IP address.
 			 */
 			error = nfsrpc_fillsa(nmp, &ssin, &ssin6, safilled,
 			    gotvers, gotminor, &dsp, p);
 		}
 		if (error == 0) {
 			KASSERT(gotdspp != NULL, ("gotdspp is NULL"));
 			*gotdspp = dsp;
 		}
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	if (error != 0 && ndi != NULL)
 		nfscl_freedevinfo(ndi);
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 LayoutCommit.
  */
 int
 nfsrpc_layoutcommit(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
     uint64_t off, uint64_t len, uint64_t lastbyte, nfsv4stateid_t *stateidp,
     int layouttype, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LAYOUTCOMMIT, nmp, fh, fhlen, NULL, NULL,
 	    0, 0, cred);
 	NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 	    NFSX_STATEID);
 	txdr_hyper(off, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	tl += 2;
 	if (reclaim != 0)
 		*tl++ = newnfs_true;
 	else
 		*tl++ = newnfs_false;
 	*tl++ = txdr_unsigned(stateidp->seqid);
 	*tl++ = stateidp->other[0];
 	*tl++ = stateidp->other[1];
 	*tl++ = stateidp->other[2];
 	*tl++ = newnfs_true;
 	if (lastbyte < off)
 		lastbyte = off;
 	else if (lastbyte >= (off + len))
 		lastbyte = off + len - 1;
 	txdr_hyper(lastbyte, tl);
 	tl += 2;
 	*tl++ = newnfs_false;
 	*tl++ = txdr_unsigned(layouttype);
 	/* All supported layouts are 0 length. */
 	*tl = txdr_unsigned(0);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 LayoutReturn.
  */
 int
 nfsrpc_layoutreturn(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
     int layouttype, uint32_t iomode, int layoutreturn, uint64_t offset,
     uint64_t len, nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
     uint32_t stat, uint32_t op, char *devid)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	uint64_t tu64;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LAYOUTRETURN, nmp, fh, fhlen, NULL, NULL,
 	    0, 0, cred);
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 	if (reclaim != 0)
 		*tl++ = newnfs_true;
 	else
 		*tl++ = newnfs_false;
 	*tl++ = txdr_unsigned(layouttype);
 	*tl++ = txdr_unsigned(iomode);
 	*tl = txdr_unsigned(layoutreturn);
 	if (layoutreturn == NFSLAYOUTRETURN_FILE) {
 		NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
 		    NFSX_UNSIGNED);
 		txdr_hyper(offset, tl);
 		tl += 2;
 		txdr_hyper(len, tl);
 		tl += 2;
 		NFSCL_DEBUG(4, "layoutret stseq=%d\n", (int)stateidp->seqid);
 		*tl++ = txdr_unsigned(stateidp->seqid);
 		*tl++ = stateidp->other[0];
 		*tl++ = stateidp->other[1];
 		*tl++ = stateidp->other[2];
 		if (layouttype == NFSLAYOUT_NFSV4_1_FILES)
 			*tl = txdr_unsigned(0);
 		else if (layouttype == NFSLAYOUT_FLEXFILE) {
 			if (stat != 0) {
 				*tl = txdr_unsigned(2 * NFSX_HYPER +
 				    NFSX_STATEID + NFSX_V4DEVICEID + 5 *
 				    NFSX_UNSIGNED);
 				NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER +
 				    NFSX_STATEID + NFSX_V4DEVICEID + 5 *
 				    NFSX_UNSIGNED);
 				*tl++ = txdr_unsigned(1);	/* One error. */
 				tu64 = 0;			/* Offset. */
 				txdr_hyper(tu64, tl); tl += 2;
 				tu64 = UINT64_MAX;		/* Length. */
 				txdr_hyper(tu64, tl); tl += 2;
 				NFSBCOPY(stateidp, tl, NFSX_STATEID);
 				tl += (NFSX_STATEID / NFSX_UNSIGNED);
 				*tl++ = txdr_unsigned(1);	/* One error. */
 				NFSBCOPY(devid, tl, NFSX_V4DEVICEID);
 				tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 				*tl++ = txdr_unsigned(stat);
 				*tl++ = txdr_unsigned(op);
 			} else {
 				*tl = txdr_unsigned(2 * NFSX_UNSIGNED);
 				NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 				/* No ioerrs. */
 				*tl++ = 0;
 			}
 			*tl = 0;	/* No stats yet. */
 		}
 	}
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		if (*tl != 0) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_STATEID);
 			stateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
 			stateidp->other[0] = *tl++;
 			stateidp->other[1] = *tl++;
 			stateidp->other[2] = *tl;
 		}
 	} else
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Do the NFSv4.2 LayoutError.
  */
 static int
 nfsrpc_layouterror(struct nfsmount *nmp, uint8_t *fh, int fhlen, uint64_t offset,
     uint64_t len, nfsv4stateid_t *stateidp, struct ucred *cred, NFSPROC_T *p,
     uint32_t stat, uint32_t op, char *devid)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LAYOUTERROR, nmp, fh, fhlen, NULL, NULL,
 	    0, 0, cred);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_STATEID +
 	    NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
 	txdr_hyper(offset, tl); tl += 2;
 	txdr_hyper(len, tl); tl += 2;
 	*tl++ = txdr_unsigned(stateidp->seqid);
 	*tl++ = stateidp->other[0];
 	*tl++ = stateidp->other[1];
 	*tl++ = stateidp->other[2];
 	*tl++ = txdr_unsigned(1);
 	NFSBCOPY(devid, tl, NFSX_V4DEVICEID);
 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(stat);
 	*tl = txdr_unsigned(op);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Acquire a layout and devinfo, if possible. The caller must have acquired
  * a reference count on the nfsclclient structure before calling this.
  * Return the layout in lypp with a reference count on it, if successful.
  */
 static int
 nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, struct nfsfh *nfhp,
     int iomode, uint32_t rw, uint32_t *notifybitsp, nfsv4stateid_t *stateidp,
     uint64_t off, struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfscllayout *lyp;
 	struct nfsclflayout *flp;
 	struct nfsclflayouthead flh;
 	int error = 0, islocked, layoutlen, layouttype, recalled, retonclose;
 	nfsv4stateid_t stateid;
 	struct nfsclsession *tsep;
 
 	*lypp = NULL;
 	if (NFSHASFLEXFILE(nmp))
 		layouttype = NFSLAYOUT_FLEXFILE;
 	else
 		layouttype = NFSLAYOUT_NFSV4_1_FILES;
 	/*
 	 * If lyp is returned non-NULL, there will be a refcnt (shared lock)
 	 * on it, iff flp != NULL or a lock (exclusive lock) on it iff
 	 * flp == NULL.
 	 */
 	lyp = nfscl_getlayout(nmp->nm_clp, nfhp->nfh_fh, nfhp->nfh_len,
 	    off, rw, &flp, &recalled);
 	islocked = 0;
 	if (lyp == NULL || flp == NULL) {
 		if (recalled != 0)
 			return (EIO);
 		LIST_INIT(&flh);
 		tsep = nfsmnt_mdssession(nmp);
 		layoutlen = tsep->nfsess_maxcache -
 		    (NFSX_STATEID + 3 * NFSX_UNSIGNED);
 		if (lyp == NULL) {
 			stateid.seqid = 0;
 			stateid.other[0] = stateidp->other[0];
 			stateid.other[1] = stateidp->other[1];
 			stateid.other[2] = stateidp->other[2];
 			error = nfsrpc_layoutget(nmp, nfhp->nfh_fh,
 			    nfhp->nfh_len, iomode, (uint64_t)0, UINT64_MAX,
 			    (uint64_t)0, layouttype, layoutlen, &stateid,
 			    &retonclose, &flh, cred, p);
 		} else {
 			islocked = 1;
 			stateid.seqid = lyp->nfsly_stateid.seqid;
 			stateid.other[0] = lyp->nfsly_stateid.other[0];
 			stateid.other[1] = lyp->nfsly_stateid.other[1];
 			stateid.other[2] = lyp->nfsly_stateid.other[2];
 			error = nfsrpc_layoutget(nmp, nfhp->nfh_fh,
 			    nfhp->nfh_len, iomode, off, UINT64_MAX,
 			    (uint64_t)0, layouttype, layoutlen, &stateid,
 			    &retonclose, &flh, cred, p);
 		}
 		error = nfsrpc_layoutgetres(nmp, vp, nfhp->nfh_fh,
 		    nfhp->nfh_len, &stateid, retonclose, notifybitsp, &lyp,
 		    &flh, layouttype, error, NULL, cred, p);
 		if (error == 0)
 			*lypp = lyp;
 		else if (islocked != 0)
 			nfscl_rellayout(lyp, 1);
 	} else
 		*lypp = lyp;
 	return (error);
 }
 
 /*
  * Do a TCP connection plus exchange id and create session.
  * If successful, a "struct nfsclds" is linked into the list for the
  * mount point and a pointer to it is returned.
  */
 static int
 nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin,
     struct sockaddr_in6 *sin6, sa_family_t af, int vers, int minorvers,
     struct nfsclds **dspp, NFSPROC_T *p)
 {
 	struct sockaddr_in *msad, *sad;
 	struct sockaddr_in6 *msad6, *sad6;
 	struct nfsclclient *clp;
 	struct nfssockreq *nrp;
 	struct nfsclds *dsp, *tdsp;
 	int error, firsttry;
 	enum nfsclds_state retv;
 	uint32_t sequenceid = 0;
 
 	KASSERT(nmp->nm_sockreq.nr_cred != NULL,
 	    ("nfsrpc_fillsa: NULL nr_cred"));
 	NFSLOCKCLSTATE();
 	clp = nmp->nm_clp;
 	NFSUNLOCKCLSTATE();
 	if (clp == NULL)
 		return (EPERM);
 	if (af == AF_INET) {
 		NFSLOCKMNT(nmp);
 		/*
 		 * Check to see if we already have a session for this
 		 * address that is usable for a DS.
 		 * Note that the MDS's address is in a different place
 		 * than the sessions already acquired for DS's.
 		 */
 		msad = (struct sockaddr_in *)nmp->nm_sockreq.nr_nam;
 		tdsp = TAILQ_FIRST(&nmp->nm_sess);
 		while (tdsp != NULL) {
 			if (msad != NULL && msad->sin_family == AF_INET &&
 			    sin->sin_addr.s_addr == msad->sin_addr.s_addr &&
 			    sin->sin_port == msad->sin_port &&
 			    (tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
 			    tdsp->nfsclds_sess.nfsess_defunct == 0) {
 				*dspp = tdsp;
 				NFSUNLOCKMNT(nmp);
 				NFSCL_DEBUG(4, "fnd same addr\n");
 				return (0);
 			}
 			tdsp = TAILQ_NEXT(tdsp, nfsclds_list);
 			if (tdsp != NULL && tdsp->nfsclds_sockp != NULL)
 				msad = (struct sockaddr_in *)
 				    tdsp->nfsclds_sockp->nr_nam;
 			else
 				msad = NULL;
 		}
 		NFSUNLOCKMNT(nmp);
 
 		/* No IP address match, so look for new/trunked one. */
 		sad = malloc(sizeof(*sad), M_SONAME, M_WAITOK | M_ZERO);
 		sad->sin_len = sizeof(*sad);
 		sad->sin_family = AF_INET;
 		sad->sin_port = sin->sin_port;
 		sad->sin_addr.s_addr = sin->sin_addr.s_addr;
-		nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
+		if (NFSHASPNFS(nmp) && NFSHASKERB(nmp)) {
+			/* For pNFS, a separate server principal is needed. */
+			nrp = malloc(sizeof(*nrp) + NI_MAXSERV + NI_MAXHOST,
+			    M_NFSSOCKREQ, M_WAITOK | M_ZERO);
+			/*
+			 * Use the latter part of nr_srvprinc as a temporary
+			 * buffer for the IP address.
+			 */
+			inet_ntoa_r(sad->sin_addr,
+			    &nrp->nr_srvprinc[NI_MAXSERV]);
+			NFSCL_DEBUG(1, "nfsrpc_fillsa: DS IP=%s\n",
+			    &nrp->nr_srvprinc[NI_MAXSERV]);
+			if (!rpc_gss_ip_to_srv_principal_call(
+			    &nrp->nr_srvprinc[NI_MAXSERV], "nfs",
+			    nrp->nr_srvprinc))
+				nrp->nr_srvprinc[0] = '\0';
+			NFSCL_DEBUG(1, "nfsrpc_fillsa: srv principal=%s\n",
+			    nrp->nr_srvprinc);
+		} else
+			nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ,
+			    M_WAITOK | M_ZERO);
 		nrp->nr_nam = (struct sockaddr *)sad;
 	} else if (af == AF_INET6) {
 		NFSLOCKMNT(nmp);
 		/*
 		 * Check to see if we already have a session for this
 		 * address that is usable for a DS.
 		 * Note that the MDS's address is in a different place
 		 * than the sessions already acquired for DS's.
 		 */
 		msad6 = (struct sockaddr_in6 *)nmp->nm_sockreq.nr_nam;
 		tdsp = TAILQ_FIRST(&nmp->nm_sess);
 		while (tdsp != NULL) {
 			if (msad6 != NULL && msad6->sin6_family == AF_INET6 &&
 			    IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
 			    &msad6->sin6_addr) &&
 			    sin6->sin6_port == msad6->sin6_port &&
 			    (tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
 			    tdsp->nfsclds_sess.nfsess_defunct == 0) {
 				*dspp = tdsp;
 				NFSUNLOCKMNT(nmp);
 				return (0);
 			}
 			tdsp = TAILQ_NEXT(tdsp, nfsclds_list);
 			if (tdsp != NULL && tdsp->nfsclds_sockp != NULL)
 				msad6 = (struct sockaddr_in6 *)
 				    tdsp->nfsclds_sockp->nr_nam;
 			else
 				msad6 = NULL;
 		}
 		NFSUNLOCKMNT(nmp);
 
 		/* No IP address match, so look for new/trunked one. */
 		sad6 = malloc(sizeof(*sad6), M_SONAME, M_WAITOK | M_ZERO);
 		sad6->sin6_len = sizeof(*sad6);
 		sad6->sin6_family = AF_INET6;
 		sad6->sin6_port = sin6->sin6_port;
 		NFSBCOPY(&sin6->sin6_addr, &sad6->sin6_addr,
 		    sizeof(struct in6_addr));
-		nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
+		if (NFSHASPNFS(nmp) && NFSHASKERB(nmp)) {
+			/* For pNFS, a separate server principal is needed. */
+			nrp = malloc(sizeof(*nrp) + NI_MAXSERV + NI_MAXHOST,
+			    M_NFSSOCKREQ, M_WAITOK | M_ZERO);
+			/*
+			 * Use the latter part of nr_srvprinc as a temporary
+			 * buffer for the IP address.
+			 */
+			inet_ntop(AF_INET6, &sad6->sin6_addr,
+			    &nrp->nr_srvprinc[NI_MAXSERV], NI_MAXHOST);
+			NFSCL_DEBUG(1, "nfsrpc_fillsa: DS IP=%s\n",
+			    &nrp->nr_srvprinc[NI_MAXSERV]);
+			if (!rpc_gss_ip_to_srv_principal_call(
+			    &nrp->nr_srvprinc[NI_MAXSERV], "nfs",
+			    nrp->nr_srvprinc))
+				nrp->nr_srvprinc[0] = '\0';
+			NFSCL_DEBUG(1, "nfsrpc_fillsa: srv principal=%s\n",
+			    nrp->nr_srvprinc);
+		} else
+			nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ,
+			    M_WAITOK | M_ZERO);
 		nrp->nr_nam = (struct sockaddr *)sad6;
 	} else
 		return (EPERM);
 
 	nrp->nr_sotype = SOCK_STREAM;
 	mtx_init(&nrp->nr_mtx, "nfssock", NULL, MTX_DEF);
 	nrp->nr_prog = NFS_PROG;
 	nrp->nr_vers = vers;
 
 	/*
 	 * Use the credentials that were used for the mount, which are
 	 * in nmp->nm_sockreq.nr_cred for newnfs_connect() etc.
 	 * Ref. counting the credentials with crhold() is probably not
 	 * necessary, since nm_sockreq.nr_cred won't be crfree()'d until
 	 * unmount, but I did it anyhow.
 	 */
 	nrp->nr_cred = crhold(nmp->nm_sockreq.nr_cred);
 	error = newnfs_connect(nmp, nrp, NULL, p, 0, false, &nrp->nr_client);
 	NFSCL_DEBUG(3, "DS connect=%d\n", error);
 
 	dsp = NULL;
 	/* Now, do the exchangeid and create session. */
 	if (error == 0) {
 		if (vers == NFS_VER4) {
 			firsttry = 0;
 			do {
 				error = nfsrpc_exchangeid(nmp, clp, nrp, 
 				    minorvers, NFSV4EXCH_USEPNFSDS, &dsp,
 				    nrp->nr_cred, p);
 				NFSCL_DEBUG(3, "DS exchangeid=%d\n", error);
 				if (error == NFSERR_MINORVERMISMATCH)
 					minorvers = NFSV42_MINORVERSION;
 			} while (error == NFSERR_MINORVERMISMATCH &&
 			    firsttry++ == 0);
 			if (error != 0)
 				newnfs_disconnect(NULL, nrp);
 		} else {
 			dsp = malloc(sizeof(struct nfsclds), M_NFSCLDS,
 			    M_WAITOK | M_ZERO);
 			dsp->nfsclds_flags |= NFSCLDS_DS;
 			dsp->nfsclds_expire = INT32_MAX; /* No renews needed. */
 			mtx_init(&dsp->nfsclds_mtx, "nfsds", NULL, MTX_DEF);
 			mtx_init(&dsp->nfsclds_sess.nfsess_mtx, "nfssession",
 			    NULL, MTX_DEF);
 		}
 	}
 	if (error == 0) {
 		dsp->nfsclds_sockp = nrp;
 		if (vers == NFS_VER4) {
 			NFSLOCKMNT(nmp);
 			retv = nfscl_getsameserver(nmp, dsp, &tdsp,
 			    &sequenceid);
 			NFSCL_DEBUG(3, "getsame ret=%d\n", retv);
 			if (retv == NFSDSP_USETHISSESSION &&
 			    nfscl_dssameconn != 0) {
 				NFSLOCKDS(tdsp);
 				tdsp->nfsclds_flags |= NFSCLDS_SAMECONN;
 				NFSUNLOCKDS(tdsp);
 				NFSUNLOCKMNT(nmp);
 				/*
 				 * If there is already a session for this
 				 * server, use it.
 				 */
 				newnfs_disconnect(NULL, nrp);
 				nfscl_freenfsclds(dsp);
 				*dspp = tdsp;
 				return (0);
 			}
 			if (retv == NFSDSP_NOTFOUND)
 				sequenceid =
 				    dsp->nfsclds_sess.nfsess_sequenceid;
 			NFSUNLOCKMNT(nmp);
 			error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
 			    nrp, dsp, sequenceid, 0, nrp->nr_cred, p);
 			NFSCL_DEBUG(3, "DS createsess=%d\n", error);
 		}
 	} else {
 		NFSFREECRED(nrp->nr_cred);
 		NFSFREEMUTEX(&nrp->nr_mtx);
 		free(nrp->nr_nam, M_SONAME);
 		free(nrp, M_NFSSOCKREQ);
 	}
 	if (error == 0) {
 		NFSCL_DEBUG(3, "add DS session\n");
 		/*
 		 * Put it at the end of the list. That way the list
 		 * is ordered by when the entry was added. This matters
 		 * since the one done first is the one that should be
 		 * used for sequencid'ing any subsequent create sessions.
 		 */
 		NFSLOCKMNT(nmp);
 		TAILQ_INSERT_TAIL(&nmp->nm_sess, dsp, nfsclds_list);
 		NFSUNLOCKMNT(nmp);
 		*dspp = dsp;
 	} else if (dsp != NULL) {
 		newnfs_disconnect(NULL, nrp);
 		nfscl_freenfsclds(dsp);
 	}
 	return (error);
 }
 
 /*
  * Do the NFSv4.1 Reclaim Complete.
  */
 int
 nfsrpc_reclaimcomplete(struct nfsmount *nmp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_RECLAIMCOMPL, nmp, NULL, 0, NULL, NULL, 0,
 	    0, cred);
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = newnfs_false;
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Initialize the slot tables for a session.
  */
 static void
 nfscl_initsessionslots(struct nfsclsession *sep)
 {
 	int i;
 
 	for (i = 0; i < NFSV4_CBSLOTS; i++) {
 		if (sep->nfsess_cbslots[i].nfssl_reply != NULL)
 			m_freem(sep->nfsess_cbslots[i].nfssl_reply);
 		NFSBZERO(&sep->nfsess_cbslots[i], sizeof(struct nfsslot));
 	}
 	for (i = 0; i < 64; i++)
 		sep->nfsess_slotseq[i] = 0;
 	sep->nfsess_slots = 0;
 	sep->nfsess_badslots = 0;
 }
 
 /*
  * Called to try and do an I/O operation via an NFSv4.1 Data Server (DS).
  */
 int
 nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     uint32_t rwaccess, int docommit, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsnode *np = VTONFS(vp);
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfscllayout *layp;
 	struct nfscldevinfo *dip;
 	struct nfsclflayout *rflp;
 	struct mbuf *m, *m2;
 	struct nfsclwritedsdorpc *drpc, *tdrpc;
 	nfsv4stateid_t stateid;
 	struct ucred *newcred;
 	uint64_t lastbyte, len, off, oresid, xfer;
 	int eof, error, firstmirror, i, iolaymode, mirrorcnt, recalled, timo;
 	void *lckp;
 	uint8_t *dev;
 	void *iovbase = NULL;
 	size_t iovlen = 0;
 	off_t offs = 0;
 	ssize_t resid = 0;
 	uint32_t op;
 
 	if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 || nfs_numnfscbd == 0 ||
 	    (np->n_flag & NNOLAYOUT) != 0)
 		return (EIO);
 	/* Now, get a reference cnt on the clientid for this mount. */
 	if (nfscl_getref(nmp) == 0)
 		return (EIO);
 
 	/* Find an appropriate stateid. */
 	newcred = NFSNEWCRED(cred);
 	error = nfscl_getstateid(vp, np->n_fhp->nfh_fh, np->n_fhp->nfh_len,
 	    rwaccess, 1, newcred, p, &stateid, &lckp);
 	if (error != 0) {
 		NFSFREECRED(newcred);
 		nfscl_relref(nmp);
 		return (error);
 	}
 	/* Search for a layout for this file. */
 	off = uiop->uio_offset;
 	layp = nfscl_getlayout(nmp->nm_clp, np->n_fhp->nfh_fh,
 	    np->n_fhp->nfh_len, off, rwaccess, &rflp, &recalled);
 	if (layp == NULL || rflp == NULL) {
 		if (recalled != 0) {
 			NFSFREECRED(newcred);
 			if (lckp != NULL)
 				nfscl_lockderef(lckp);
 			nfscl_relref(nmp);
 			return (EIO);
 		}
 		if (layp != NULL) {
 			nfscl_rellayout(layp, (rflp == NULL) ? 1 : 0);
 			layp = NULL;
 		}
 		/* Try and get a Layout, if it is supported. */
 		if (rwaccess == NFSV4OPEN_ACCESSWRITE ||
 		    (np->n_flag & NWRITEOPENED) != 0)
 			iolaymode = NFSLAYOUTIOMODE_RW;
 		else
 			iolaymode = NFSLAYOUTIOMODE_READ;
 		error = nfsrpc_getlayout(nmp, vp, np->n_fhp, iolaymode,
 		    rwaccess, NULL, &stateid, off, &layp, newcred, p);
 		if (error != 0) {
 			NFSLOCKNODE(np);
 			np->n_flag |= NNOLAYOUT;
 			NFSUNLOCKNODE(np);
 			if (lckp != NULL)
 				nfscl_lockderef(lckp);
 			NFSFREECRED(newcred);
 			if (layp != NULL)
 				nfscl_rellayout(layp, 0);
 			nfscl_relref(nmp);
 			return (error);
 		}
 	}
 
 	/*
 	 * Loop around finding a layout that works for the first part of
 	 * this I/O operation, and then call the function that actually
 	 * does the RPC.
 	 */
 	eof = 0;
 	len = (uint64_t)uiop->uio_resid;
 	while (len > 0 && error == 0 && eof == 0) {
 		off = uiop->uio_offset;
 		error = nfscl_findlayoutforio(layp, off, rwaccess, &rflp);
 		if (error == 0) {
 			oresid = xfer = (uint64_t)uiop->uio_resid;
 			if (xfer > (rflp->nfsfl_end - rflp->nfsfl_off))
 				xfer = rflp->nfsfl_end - rflp->nfsfl_off;
 			/*
 			 * For Flex File layout with mirrored DSs, select one
 			 * of them at random for reads. For writes and commits,
 			 * do all mirrors.
 			 */
 			m = NULL;
 			tdrpc = drpc = NULL;
 			firstmirror = 0;
 			mirrorcnt = 1;
 			if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0 &&
 			    (mirrorcnt = rflp->nfsfl_mirrorcnt) > 1) {
 				if (rwaccess == NFSV4OPEN_ACCESSREAD) {
 					firstmirror = arc4random() % mirrorcnt;
 					mirrorcnt = firstmirror + 1;
 				} else {
 					if (docommit == 0) {
 						/*
 						 * Save values, so uiop can be
 						 * rolled back upon a write
 						 * error.
 						 */
 						offs = uiop->uio_offset;
 						resid = uiop->uio_resid;
 						iovbase =
 						    uiop->uio_iov->iov_base;
 						iovlen = uiop->uio_iov->iov_len;
 						m = nfsm_uiombuflist(uiop, len,
 						    0);
 					}
 					tdrpc = drpc = malloc(sizeof(*drpc) *
 					    (mirrorcnt - 1), M_TEMP, M_WAITOK |
 					    M_ZERO);
 				}
 			}
 			for (i = firstmirror; i < mirrorcnt && error == 0; i++){
 				m2 = NULL;
 				if (m != NULL && i < mirrorcnt - 1)
 					m2 = m_copym(m, 0, M_COPYALL, M_WAITOK);
 				else {
 					m2 = m;
 					m = NULL;
 				}
 				if ((layp->nfsly_flags & NFSLY_FLEXFILE) != 0) {
 					dev = rflp->nfsfl_ffm[i].dev;
 					dip = nfscl_getdevinfo(nmp->nm_clp, dev,
 					    rflp->nfsfl_ffm[i].devp);
 				} else {
 					dev = rflp->nfsfl_dev;
 					dip = nfscl_getdevinfo(nmp->nm_clp, dev,
 					    rflp->nfsfl_devp);
 				}
 				if (dip != NULL) {
 					if ((rflp->nfsfl_flags & NFSFL_FLEXFILE)
 					    != 0)
 						error = nfscl_dofflayoutio(vp,
 						    uiop, iomode, must_commit,
 						    &eof, &stateid, rwaccess,
 						    dip, layp, rflp, off, xfer,
 						    i, docommit, m2, tdrpc,
 						    newcred, p);
 					else
 						error = nfscl_doflayoutio(vp,
 						    uiop, iomode, must_commit,
 						    &eof, &stateid, rwaccess,
 						    dip, layp, rflp, off, xfer,
 						    docommit, newcred, p);
 					nfscl_reldevinfo(dip);
 				} else {
 					if (m2 != NULL)
 						m_freem(m2);
 					error = EIO;
 				}
 				tdrpc++;
 			}
 			if (m != NULL)
 				m_freem(m);
 			tdrpc = drpc;
 			timo = hz / 50;		/* Wait for 20msec. */
 			if (timo < 1)
 				timo = 1;
 			for (i = firstmirror; i < mirrorcnt - 1 &&
 			    tdrpc != NULL; i++, tdrpc++) {
 				/*
 				 * For the unused drpc entries, both inprog and
 				 * err == 0, so this loop won't break.
 				 */
 				while (tdrpc->inprog != 0 && tdrpc->done == 0)
 					tsleep(&tdrpc->tsk, PVFS, "clrpcio",
 					    timo);
 				if (error == 0 && tdrpc->err != 0)
 					error = tdrpc->err;
 				if (rwaccess != NFSV4OPEN_ACCESSREAD &&
 				    docommit == 0 && *must_commit == 0 &&
 				    tdrpc->must_commit == 1)
 					*must_commit = 1;
 			}
 			free(drpc, M_TEMP);
 			if (error == 0) {
 				if (mirrorcnt > 1 && rwaccess ==
 				    NFSV4OPEN_ACCESSWRITE && docommit == 0) {
 					NFSLOCKCLSTATE();
 					layp->nfsly_flags |= NFSLY_WRITTEN;
 					NFSUNLOCKCLSTATE();
 				}
 				lastbyte = off + xfer - 1;
 				NFSLOCKCLSTATE();
 				if (lastbyte > layp->nfsly_lastbyte)
 					layp->nfsly_lastbyte = lastbyte;
 				NFSUNLOCKCLSTATE();
 			} else if (error == NFSERR_OPENMODE &&
 			    rwaccess == NFSV4OPEN_ACCESSREAD) {
 				NFSLOCKMNT(nmp);
 				nmp->nm_state |= NFSSTA_OPENMODE;
 				NFSUNLOCKMNT(nmp);
 			} else if ((error == NFSERR_NOSPC ||
 			    error == NFSERR_IO || error == NFSERR_NXIO) &&
 			    nmp->nm_minorvers == NFSV42_MINORVERSION) {
 				if (docommit != 0)
 					op = NFSV4OP_COMMIT;
 				else if (rwaccess == NFSV4OPEN_ACCESSREAD)
 					op = NFSV4OP_READ;
 				else
 					op = NFSV4OP_WRITE;
 				nfsrpc_layouterror(nmp, np->n_fhp->nfh_fh,
 				    np->n_fhp->nfh_len, off, xfer,
 				    &layp->nfsly_stateid, newcred, p, error, op,
 				    dip->nfsdi_deviceid);
 				error = EIO;
 			} else
 				error = EIO;
 			if (error == 0)
 				len -= (oresid - (uint64_t)uiop->uio_resid);
 			else if (mirrorcnt > 1 && rwaccess ==
 			    NFSV4OPEN_ACCESSWRITE && docommit == 0) {
 				/*
 				 * In case the rpc gets retried, roll the
 				 * uio fields changed by nfsm_uiombuflist()
 				 * back.
 				 */
 				uiop->uio_offset = offs;
 				uiop->uio_resid = resid;
 				uiop->uio_iov->iov_base = iovbase;
 				uiop->uio_iov->iov_len = iovlen;
 			}
 		}
 	}
 	if (lckp != NULL)
 		nfscl_lockderef(lckp);
 	NFSFREECRED(newcred);
 	nfscl_rellayout(layp, 0);
 	nfscl_relref(nmp);
 	return (error);
 }
 
 /*
  * Find a file layout that will handle the first bytes of the requested
  * range and return the information from it needed to the I/O operation.
  */
 int
 nfscl_findlayoutforio(struct nfscllayout *lyp, uint64_t off, uint32_t rwaccess,
     struct nfsclflayout **retflpp)
 {
 	struct nfsclflayout *flp, *nflp, *rflp;
 	uint32_t rw;
 
 	rflp = NULL;
 	rw = rwaccess;
 	/* For reading, do the Read list first and then the Write list. */
 	do {
 		if (rw == NFSV4OPEN_ACCESSREAD)
 			flp = LIST_FIRST(&lyp->nfsly_flayread);
 		else
 			flp = LIST_FIRST(&lyp->nfsly_flayrw);
 		while (flp != NULL) {
 			nflp = LIST_NEXT(flp, nfsfl_list);
 			if (flp->nfsfl_off > off)
 				break;
 			if (flp->nfsfl_end > off &&
 			    (rflp == NULL || rflp->nfsfl_end < flp->nfsfl_end))
 				rflp = flp;
 			flp = nflp;
 		}
 		if (rw == NFSV4OPEN_ACCESSREAD)
 			rw = NFSV4OPEN_ACCESSWRITE;
 		else
 			rw = 0;
 	} while (rw != 0);
 	if (rflp != NULL) {
 		/* This one covers the most bytes starting at off. */
 		*retflpp = rflp;
 		return (0);
 	}
 	return (EIO);
 }
 
 /*
  * Do I/O using an NFSv4.1 or NFSv4.2 file layout.
  */
 static int
 nfscl_doflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo *dp,
     struct nfscllayout *lyp, struct nfsclflayout *flp, uint64_t off,
     uint64_t len, int docommit, struct ucred *cred, NFSPROC_T *p)
 {
 	uint64_t io_off, rel_off, stripe_unit_size, transfer, xfer;
 	int commit_thru_mds, error, stripe_index, stripe_pos, minorvers;
 	struct nfsnode *np;
 	struct nfsfh *fhp;
 	struct nfsclds **dspp;
 
 	np = VTONFS(vp);
 	rel_off = off - flp->nfsfl_patoff;
 	stripe_unit_size = flp->nfsfl_util & NFSFLAYUTIL_STRIPE_MASK;
 	stripe_pos = (rel_off / stripe_unit_size + flp->nfsfl_stripe1) %
 	    dp->nfsdi_stripecnt;
 	transfer = stripe_unit_size - (rel_off % stripe_unit_size);
 	error = 0;
 
 	/* Loop around, doing I/O for each stripe unit. */
 	while (len > 0 && error == 0) {
 		stripe_index = nfsfldi_stripeindex(dp, stripe_pos);
 		dspp = nfsfldi_addr(dp, stripe_index);
 		if (((*dspp)->nfsclds_flags & NFSCLDS_MINORV2) != 0)
 			minorvers = NFSV42_MINORVERSION;
 		else
 			minorvers = NFSV41_MINORVERSION;
 		if (len > transfer && docommit == 0)
 			xfer = transfer;
 		else
 			xfer = len;
 		if ((flp->nfsfl_util & NFSFLAYUTIL_DENSE) != 0) {
 			/* Dense layout. */
 			if (stripe_pos >= flp->nfsfl_fhcnt)
 				return (EIO);
 			fhp = flp->nfsfl_fh[stripe_pos];
 			io_off = (rel_off / (stripe_unit_size *
 			    dp->nfsdi_stripecnt)) * stripe_unit_size +
 			    rel_off % stripe_unit_size;
 		} else {
 			/* Sparse layout. */
 			if (flp->nfsfl_fhcnt > 1) {
 				if (stripe_index >= flp->nfsfl_fhcnt)
 					return (EIO);
 				fhp = flp->nfsfl_fh[stripe_index];
 			} else if (flp->nfsfl_fhcnt == 1)
 				fhp = flp->nfsfl_fh[0];
 			else
 				fhp = np->n_fhp;
 			io_off = off;
 		}
 		if ((flp->nfsfl_util & NFSFLAYUTIL_COMMIT_THRU_MDS) != 0) {
 			commit_thru_mds = 1;
 			if (docommit != 0)
 				error = EIO;
 		} else {
 			commit_thru_mds = 0;
 			NFSLOCKNODE(np);
 			np->n_flag |= NDSCOMMIT;
 			NFSUNLOCKNODE(np);
 		}
 		if (docommit != 0) {
 			if (error == 0)
 				error = nfsrpc_commitds(vp, io_off, xfer,
 				    *dspp, fhp, NFS_VER4, minorvers, cred, p);
 			if (error == 0) {
 				/*
 				 * Set both eof and uio_resid = 0 to end any
 				 * loops.
 				 */
 				*eofp = 1;
 				uiop->uio_resid = 0;
 			} else {
 				NFSLOCKNODE(np);
 				np->n_flag &= ~NDSCOMMIT;
 				NFSUNLOCKNODE(np);
 			}
 		} else if (rwflag == NFSV4OPEN_ACCESSREAD)
 			error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
 			    io_off, xfer, fhp, 0, NFS_VER4, minorvers, cred, p);
 		else {
 			error = nfsrpc_writeds(vp, uiop, iomode, must_commit,
 			    stateidp, *dspp, io_off, xfer, fhp, commit_thru_mds,
 			    0, NFS_VER4, minorvers, cred, p);
 			if (error == 0) {
 				NFSLOCKCLSTATE();
 				lyp->nfsly_flags |= NFSLY_WRITTEN;
 				NFSUNLOCKCLSTATE();
 			}
 		}
 		if (error == 0) {
 			transfer = stripe_unit_size;
 			stripe_pos = (stripe_pos + 1) % dp->nfsdi_stripecnt;
 			len -= xfer;
 			off += xfer;
 		}
 	}
 	return (error);
 }
 
 /*
  * Do I/O using an NFSv4.1 flex file layout.
  */
 static int
 nfscl_dofflayoutio(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     int *eofp, nfsv4stateid_t *stateidp, int rwflag, struct nfscldevinfo *dp,
     struct nfscllayout *lyp, struct nfsclflayout *flp, uint64_t off,
     uint64_t len, int mirror, int docommit, struct mbuf *mp,
     struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
 {
 	uint64_t xfer;
 	int error;
 	struct nfsnode *np;
 	struct nfsfh *fhp;
 	struct nfsclds **dspp;
 	struct ucred *tcred;
 	struct mbuf *m, *m2;
 	uint32_t copylen;
 
 	np = VTONFS(vp);
 	error = 0;
 	NFSCL_DEBUG(4, "nfscl_dofflayoutio: off=%ju len=%ju\n", (uintmax_t)off,
 	    (uintmax_t)len);
 	/* Loop around, doing I/O for each stripe unit. */
 	while (len > 0 && error == 0) {
 		dspp = nfsfldi_addr(dp, 0);
 		fhp = flp->nfsfl_ffm[mirror].fh[dp->nfsdi_versindex];
 		stateidp = &flp->nfsfl_ffm[mirror].st;
 		NFSCL_DEBUG(4, "mirror=%d vind=%d fhlen=%d st.seqid=0x%x\n",
 		    mirror, dp->nfsdi_versindex, fhp->nfh_len, stateidp->seqid);
 		if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0) {
 			tcred = NFSNEWCRED(cred);
 			tcred->cr_uid = flp->nfsfl_ffm[mirror].user;
 			tcred->cr_groups[0] = flp->nfsfl_ffm[mirror].group;
 			tcred->cr_ngroups = 1;
 		} else
 			tcred = cred;
 		if (rwflag == NFSV4OPEN_ACCESSREAD)
 			copylen = dp->nfsdi_rsize;
 		else {
 			copylen = dp->nfsdi_wsize;
 			if (len > copylen && mp != NULL) {
 				/*
 				 * When a mirrored configuration needs to do
 				 * multiple writes to each mirror, all writes
 				 * except the last one must be a multiple of
 				 * 4 bytes.  This is required so that the XDR
 				 * does not need padding.
 				 * If possible, clip the size to an exact
 				 * multiple of the mbuf length, so that the
 				 * split will be on an mbuf boundary.
 				 */
 				copylen &= 0xfffffffc;
 				if (copylen > mp->m_len)
 					copylen = copylen / mp->m_len *
 					    mp->m_len;
 			}
 		}
 		NFSLOCKNODE(np);
 		np->n_flag |= NDSCOMMIT;
 		NFSUNLOCKNODE(np);
 		if (len > copylen && docommit == 0)
 			xfer = copylen;
 		else
 			xfer = len;
 		if (docommit != 0) {
 			if (error == 0) {
 				/*
 				 * Do last mirrored DS commit with this thread.
 				 */
 				if (mirror < flp->nfsfl_mirrorcnt - 1)
 					error = nfsio_commitds(vp, off, xfer,
 					    *dspp, fhp, dp->nfsdi_vers,
 					    dp->nfsdi_minorvers, drpc, tcred,
 					    p);
 				else
 					error = nfsrpc_commitds(vp, off, xfer,
 					    *dspp, fhp, dp->nfsdi_vers,
 					    dp->nfsdi_minorvers, tcred, p);
 				NFSCL_DEBUG(4, "commitds=%d\n", error);
 				if (error != 0 && error != EACCES && error !=
 				    ESTALE) {
 					NFSCL_DEBUG(4,
 					    "DS layreterr for commit\n");
 					nfscl_dserr(NFSV4OP_COMMIT, error, dp,
 					    lyp, *dspp);
 				}
 			}
 			NFSCL_DEBUG(4, "aft nfsio_commitds=%d\n", error);
 			if (error == 0) {
 				/*
 				 * Set both eof and uio_resid = 0 to end any
 				 * loops.
 				 */
 				*eofp = 1;
 				uiop->uio_resid = 0;
 			} else {
 				NFSLOCKNODE(np);
 				np->n_flag &= ~NDSCOMMIT;
 				NFSUNLOCKNODE(np);
 			}
 		} else if (rwflag == NFSV4OPEN_ACCESSREAD) {
 			error = nfsrpc_readds(vp, uiop, stateidp, eofp, *dspp,
 			    off, xfer, fhp, 1, dp->nfsdi_vers,
 			    dp->nfsdi_minorvers, tcred, p);
 			NFSCL_DEBUG(4, "readds=%d\n", error);
 			if (error != 0 && error != EACCES && error != ESTALE) {
 				NFSCL_DEBUG(4, "DS layreterr for read\n");
 				nfscl_dserr(NFSV4OP_READ, error, dp, lyp,
 				    *dspp);
 			}
 		} else {
 			if (flp->nfsfl_mirrorcnt == 1) {
 				error = nfsrpc_writeds(vp, uiop, iomode,
 				    must_commit, stateidp, *dspp, off, xfer,
 				    fhp, 0, 1, dp->nfsdi_vers,
 				    dp->nfsdi_minorvers, tcred, p);
 				if (error == 0) {
 					NFSLOCKCLSTATE();
 					lyp->nfsly_flags |= NFSLY_WRITTEN;
 					NFSUNLOCKCLSTATE();
 				}
 			} else {
 				m = mp;
 				if (xfer < len) {
 					/* The mbuf list must be split. */
 					m2 = nfsm_split(mp, xfer);
 					if (m2 != NULL)
 						mp = m2;
 					else {
 						m_freem(mp);
 						error = EIO;
 					}
 				}
 				NFSCL_DEBUG(4, "mcopy len=%jd xfer=%jd\n",
 				    (uintmax_t)len, (uintmax_t)xfer);
 				/*
 				 * Do last write to a mirrored DS with this
 				 * thread.
 				 */
 				if (error == 0) {
 					if (mirror < flp->nfsfl_mirrorcnt - 1)
 						error = nfsio_writedsmir(vp,
 						    iomode, must_commit,
 						    stateidp, *dspp, off,
 						    xfer, fhp, m,
 						    dp->nfsdi_vers,
 						    dp->nfsdi_minorvers, drpc,
 						    tcred, p);
 					else
 						error = nfsrpc_writedsmir(vp,
 						    iomode, must_commit,
 						    stateidp, *dspp, off,
 						    xfer, fhp, m,
 						    dp->nfsdi_vers,
 						    dp->nfsdi_minorvers, tcred,
 						    p);
 				}
 				NFSCL_DEBUG(4, "nfsio_writedsmir=%d\n", error);
 				if (error != 0 && error != EACCES && error !=
 				    ESTALE) {
 					NFSCL_DEBUG(4,
 					    "DS layreterr for write\n");
 					nfscl_dserr(NFSV4OP_WRITE, error, dp,
 					    lyp, *dspp);
 				}
 			}
 		}
 		NFSCL_DEBUG(4, "aft read/writeds=%d\n", error);
 		if (error == 0) {
 			len -= xfer;
 			off += xfer;
 		}
 		if ((dp->nfsdi_flags & NFSDI_TIGHTCOUPLED) == 0)
 			NFSFREECRED(tcred);
 	}
 	NFSCL_DEBUG(4, "eo nfscl_dofflayoutio=%d\n", error);
 	return (error);
 }
 
 /*
  * The actual read RPC done to a DS.
  */
 static int
 nfsrpc_readds(vnode_t vp, struct uio *uiop, nfsv4stateid_t *stateidp, int *eofp,
     struct nfsclds *dsp, uint64_t io_off, int len, struct nfsfh *fhp, int flex,
     int vers, int minorvers, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int attrflag, error, retlen;
 	struct nfsrv_descript nfsd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfssockreq *nrp;
 	struct nfsvattr na;
 
 	nd->nd_mrep = NULL;
 	if (vers == 0 || vers == NFS_VER4) {
 		nfscl_reqstart(nd, NFSPROC_READDS, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		vers = NFS_VER4;
 		NFSCL_DEBUG(4, "nfsrpc_readds: vers4 minvers=%d\n", minorvers);
 		if (flex != 0)
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 		else
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSEQIDZERO);
 	} else {
 		nfscl_reqstart(nd, NFSPROC_READ, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		NFSDECRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_READ]);
 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_READDS]);
 		NFSCL_DEBUG(4, "nfsrpc_readds: vers3\n");
 	}
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED * 3);
 	txdr_hyper(io_off, tl);
 	*(tl + 2) = txdr_unsigned(len);
 	nrp = dsp->nfsclds_sockp;
 	NFSCL_DEBUG(4, "nfsrpc_readds: nrp=%p\n", nrp);
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, vers, NULL, 1, NULL, &dsp->nfsclds_sess);
 	NFSCL_DEBUG(4, "nfsrpc_readds: stat=%d err=%d\n", nd->nd_repstat,
 	    error);
 	if (error != 0)
 		return (error);
 	if (vers == NFS_VER3) {
 		error = nfscl_postop_attr(nd, &na, &attrflag);
 		NFSCL_DEBUG(4, "nfsrpc_readds: postop=%d\n", error);
 		if (error != 0)
 			goto nfsmout;
 	}
 	if (nd->nd_repstat != 0) {
 		error = nd->nd_repstat;
 		goto nfsmout;
 	}
 	if (vers == NFS_VER3) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		*eofp = fxdr_unsigned(int, *(tl + 1));
 	} else {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		*eofp = fxdr_unsigned(int, *tl);
 	}
 	NFSM_STRSIZ(retlen, len);
 	NFSCL_DEBUG(4, "nfsrpc_readds: retlen=%d eof=%d\n", retlen, *eofp);
 	error = nfsm_mbufuio(nd, uiop, retlen);
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The actual write RPC done to a DS.
  */
 static int
 nfsrpc_writeds(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
     nfsv4stateid_t *stateidp, struct nfsclds *dsp, uint64_t io_off, int len,
     struct nfsfh *fhp, int commit_thru_mds, int flex, int vers, int minorvers,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	int attrflag, error, rlen, commit, committed = NFSWRITE_FILESYNC;
 	int32_t backup;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfssockreq *nrp;
 	struct nfsvattr na;
 
 	KASSERT(uiop->uio_iovcnt == 1, ("nfs: writerpc iovcnt > 1"));
 	nd->nd_mrep = NULL;
 	if (vers == 0 || vers == NFS_VER4) {
 		nfscl_reqstart(nd, NFSPROC_WRITEDS, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		NFSCL_DEBUG(4, "nfsrpc_writeds: vers4 minvers=%d\n", minorvers);
 		vers = NFS_VER4;
 		if (flex != 0)
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 		else
 			nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSEQIDZERO);
 		NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
 	} else {
 		nfscl_reqstart(nd, NFSPROC_WRITE, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		NFSDECRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_WRITE]);
 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_WRITEDS]);
 		NFSCL_DEBUG(4, "nfsrpc_writeds: vers3\n");
 		NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 3 * NFSX_UNSIGNED);
 	}
 	txdr_hyper(io_off, tl);
 	tl += 2;
 	if (vers == NFS_VER3)
 		*tl++ = txdr_unsigned(len);
 	*tl++ = txdr_unsigned(*iomode);
 	*tl = txdr_unsigned(len);
 	nfsm_uiombuf(nd, uiop, len);
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, vers, NULL, 1, NULL, &dsp->nfsclds_sess);
 	NFSCL_DEBUG(4, "nfsrpc_writeds: err=%d stat=%d\n", error,
 	    nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat != 0) {
 		/*
 		 * In case the rpc gets retried, roll
 		 * the uio fields changed by nfsm_uiombuf()
 		 * back.
 		 */
 		uiop->uio_offset -= len;
 		uiop->uio_resid += len;
 		uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base - len;
 		uiop->uio_iov->iov_len += len;
 		error = nd->nd_repstat;
 	} else {
 		if (vers == NFS_VER3) {
 			error = nfscl_wcc_data(nd, vp, &na, &attrflag, NULL,
 			    NULL);
 			NFSCL_DEBUG(4, "nfsrpc_writeds: wcc_data=%d\n", error);
 			if (error != 0)
 				goto nfsmout;
 		}
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF);
 		rlen = fxdr_unsigned(int, *tl++);
 		NFSCL_DEBUG(4, "nfsrpc_writeds: len=%d rlen=%d\n", len, rlen);
 		if (rlen == 0) {
 			error = NFSERR_IO;
 			goto nfsmout;
 		} else if (rlen < len) {
 			backup = len - rlen;
 			uiop->uio_iov->iov_base =
 			    (char *)uiop->uio_iov->iov_base - backup;
 			uiop->uio_iov->iov_len += backup;
 			uiop->uio_offset -= backup;
 			uiop->uio_resid += backup;
 			len = rlen;
 		}
 		commit = fxdr_unsigned(int, *tl++);
 
 		/*
 		 * Return the lowest commitment level
 		 * obtained by any of the RPCs.
 		 */
 		if (committed == NFSWRITE_FILESYNC)
 			committed = commit;
 		else if (committed == NFSWRITE_DATASYNC &&
 		    commit == NFSWRITE_UNSTABLE)
 			committed = commit;
 		if (commit_thru_mds != 0) {
 			NFSLOCKMNT(nmp);
 			if (!NFSHASWRITEVERF(nmp)) {
 				NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 				NFSSETWRITEVERF(nmp);
 			} else if (NFSBCMP(tl, nmp->nm_verf, NFSX_VERF) &&
 			    *must_commit != 2) {
 				*must_commit = 1;
 				NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 			}
 			NFSUNLOCKMNT(nmp);
 		} else {
 			NFSLOCKDS(dsp);
 			if ((dsp->nfsclds_flags & NFSCLDS_HASWRITEVERF) == 0) {
 				NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
 				dsp->nfsclds_flags |= NFSCLDS_HASWRITEVERF;
 			} else if (NFSBCMP(tl, dsp->nfsclds_verf, NFSX_VERF) &&
 			    *must_commit != 2) {
 				*must_commit = 1;
 				NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
 			}
 			NFSUNLOCKDS(dsp);
 		}
 	}
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	*iomode = committed;
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	return (error);
 }
 
 /*
  * The actual write RPC done to a DS.
  * This variant is called from a separate kernel process for mirrors.
  * Any short write is considered an IO error.
  */
 static int
 nfsrpc_writedsmir(vnode_t vp, int *iomode, int *must_commit,
     nfsv4stateid_t *stateidp, struct nfsclds *dsp, uint64_t io_off, int len,
     struct nfsfh *fhp, struct mbuf *m, int vers, int minorvers,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	int attrflag, error, commit, committed = NFSWRITE_FILESYNC, rlen;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfssockreq *nrp;
 	struct nfsvattr na;
 
 	nd->nd_mrep = NULL;
 	if (vers == 0 || vers == NFS_VER4) {
 		nfscl_reqstart(nd, NFSPROC_WRITEDS, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		vers = NFS_VER4;
 		NFSCL_DEBUG(4, "nfsrpc_writedsmir: vers4 minvers=%d\n",
 		    minorvers);
 		nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 		NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
 	} else {
 		nfscl_reqstart(nd, NFSPROC_WRITE, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		NFSDECRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_WRITE]);
 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_WRITEDS]);
 		NFSCL_DEBUG(4, "nfsrpc_writedsmir: vers3\n");
 		NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 3 * NFSX_UNSIGNED);
 	}
 	txdr_hyper(io_off, tl);
 	tl += 2;
 	if (vers == NFS_VER3)
 		*tl++ = txdr_unsigned(len);
 	*tl++ = txdr_unsigned(*iomode);
 	*tl = txdr_unsigned(len);
 	if (len > 0) {
 		/* Put data in mbuf chain. */
 		nd->nd_mb->m_next = m;
 	}
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, vers, NULL, 1, NULL, &dsp->nfsclds_sess);
 	NFSCL_DEBUG(4, "nfsrpc_writedsmir: err=%d stat=%d\n", error,
 	    nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	else {
 		if (vers == NFS_VER3) {
 			error = nfscl_wcc_data(nd, vp, &na, &attrflag, NULL,
 			    NULL);
 			NFSCL_DEBUG(4, "nfsrpc_writedsmir: wcc_data=%d\n",
 			    error);
 			if (error != 0)
 				goto nfsmout;
 		}
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF);
 		rlen = fxdr_unsigned(int, *tl++);
 		NFSCL_DEBUG(4, "nfsrpc_writedsmir: len=%d rlen=%d\n", len,
 		    rlen);
 		if (rlen != len) {
 			error = NFSERR_IO;
 			NFSCL_DEBUG(4, "nfsrpc_writedsmir: len=%d rlen=%d\n",
 			    len, rlen);
 			goto nfsmout;
 		}
 		commit = fxdr_unsigned(int, *tl++);
 
 		/*
 		 * Return the lowest commitment level
 		 * obtained by any of the RPCs.
 		 */
 		if (committed == NFSWRITE_FILESYNC)
 			committed = commit;
 		else if (committed == NFSWRITE_DATASYNC &&
 		    commit == NFSWRITE_UNSTABLE)
 			committed = commit;
 		NFSLOCKDS(dsp);
 		if ((dsp->nfsclds_flags & NFSCLDS_HASWRITEVERF) == 0) {
 			NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
 			dsp->nfsclds_flags |= NFSCLDS_HASWRITEVERF;
 		} else if (NFSBCMP(tl, dsp->nfsclds_verf, NFSX_VERF) &&
 		    *must_commit != 2) {
 			*must_commit = 1;
 			NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
 		}
 		NFSUNLOCKDS(dsp);
 	}
 nfsmout:
 	if (nd->nd_mrep != NULL)
 		m_freem(nd->nd_mrep);
 	*iomode = committed;
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	return (error);
 }
 
 /*
  * Start up the thread that will execute nfsrpc_writedsmir().
  */
 static void
 start_writedsmir(void *arg, int pending)
 {
 	struct nfsclwritedsdorpc *drpc;
 
 	drpc = (struct nfsclwritedsdorpc *)arg;
 	drpc->err = nfsrpc_writedsmir(drpc->vp, &drpc->iomode,
 	    &drpc->must_commit, drpc->stateidp, drpc->dsp, drpc->off, drpc->len,
 	    drpc->fhp, drpc->m, drpc->vers, drpc->minorvers, drpc->cred,
 	    drpc->p);
 	drpc->done = 1;
 	crfree(drpc->cred);
 	NFSCL_DEBUG(4, "start_writedsmir: err=%d\n", drpc->err);
 }
 
 /*
  * Set up the write DS mirror call for the pNFS I/O thread.
  */
 static int
 nfsio_writedsmir(vnode_t vp, int *iomode, int *must_commit,
     nfsv4stateid_t *stateidp, struct nfsclds *dsp, uint64_t off, int len,
     struct nfsfh *fhp, struct mbuf *m, int vers, int minorvers,
     struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
 {
 	int error, ret;
 
 	error = 0;
 	drpc->done = 0;
 	drpc->vp = vp;
 	drpc->iomode = *iomode;
 	drpc->must_commit = *must_commit;
 	drpc->stateidp = stateidp;
 	drpc->dsp = dsp;
 	drpc->off = off;
 	drpc->len = len;
 	drpc->fhp = fhp;
 	drpc->m = m;
 	drpc->vers = vers;
 	drpc->minorvers = minorvers;
 	drpc->cred = crhold(cred);
 	drpc->p = p;
 	drpc->inprog = 0;
 	ret = EIO;
 	if (nfs_pnfsiothreads != 0) {
 		ret = nfs_pnfsio(start_writedsmir, drpc);
 		NFSCL_DEBUG(4, "nfsio_writedsmir: nfs_pnfsio=%d\n", ret);
 	}
 	if (ret != 0) {
 		error = nfsrpc_writedsmir(vp, iomode, &drpc->must_commit,
 		    stateidp, dsp, off, len, fhp, m, vers, minorvers, cred, p);
 		crfree(drpc->cred);
 	}
 	NFSCL_DEBUG(4, "nfsio_writedsmir: error=%d\n", error);
 	return (error);
 }
 
 /*
  * Free up the nfsclds structure.
  */
 void
 nfscl_freenfsclds(struct nfsclds *dsp)
 {
 	int i;
 
 	if (dsp == NULL)
 		return;
 	if (dsp->nfsclds_sockp != NULL) {
 		NFSFREECRED(dsp->nfsclds_sockp->nr_cred);
 		NFSFREEMUTEX(&dsp->nfsclds_sockp->nr_mtx);
 		free(dsp->nfsclds_sockp->nr_nam, M_SONAME);
 		free(dsp->nfsclds_sockp, M_NFSSOCKREQ);
 	}
 	NFSFREEMUTEX(&dsp->nfsclds_mtx);
 	NFSFREEMUTEX(&dsp->nfsclds_sess.nfsess_mtx);
 	for (i = 0; i < NFSV4_CBSLOTS; i++) {
 		if (dsp->nfsclds_sess.nfsess_cbslots[i].nfssl_reply != NULL)
 			m_freem(
 			    dsp->nfsclds_sess.nfsess_cbslots[i].nfssl_reply);
 	}
 	free(dsp, M_NFSCLDS);
 }
 
 static enum nfsclds_state
 nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp,
     struct nfsclds **retdspp, uint32_t *sequencep)
 {
 	struct nfsclds *dsp;
 	int fndseq;
 
 	/*
 	 * Search the list of nfsclds structures for one with the same
 	 * server.
 	 */
 	fndseq = 0;
 	TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
 		if (dsp->nfsclds_servownlen == newdsp->nfsclds_servownlen &&
 		    dsp->nfsclds_servownlen != 0 &&
 		    !NFSBCMP(dsp->nfsclds_serverown, newdsp->nfsclds_serverown,
 		    dsp->nfsclds_servownlen) &&
 		    dsp->nfsclds_sess.nfsess_defunct == 0) {
 			NFSCL_DEBUG(4, "fnd same fdsp=%p dsp=%p flg=0x%x\n",
 			    TAILQ_FIRST(&nmp->nm_sess), dsp,
 			    dsp->nfsclds_flags);
 			if (fndseq == 0) {
 				/* Get sequenceid# from first entry. */
 				*sequencep =
 				    dsp->nfsclds_sess.nfsess_sequenceid;
 				fndseq = 1;
 			}
 			/* Server major id matches. */
 			if ((dsp->nfsclds_flags & NFSCLDS_DS) != 0) {
 				*retdspp = dsp;
 				return (NFSDSP_USETHISSESSION);
 			}
 		}
 	}
 	if (fndseq != 0)
 		return (NFSDSP_SEQTHISSESSION);
 	return (NFSDSP_NOTFOUND);
 }
 
 /*
  * NFS commit rpc to a NFSv4.1 DS.
  */
 static int
 nfsrpc_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
     struct nfsfh *fhp, int vers, int minorvers, struct ucred *cred,
     NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfssockreq *nrp;
 	struct nfsvattr na;
 	int attrflag, error;
 
 	nd->nd_mrep = NULL;
 	if (vers == 0 || vers == NFS_VER4) {
 		nfscl_reqstart(nd, NFSPROC_COMMITDS, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		vers = NFS_VER4;
 	} else {
 		nfscl_reqstart(nd, NFSPROC_COMMIT, nmp, fhp->nfh_fh,
 		    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers,
 		    NULL);
 		NFSDECRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_COMMIT]);
 		NFSINCRGLOBAL(nfsstatsv1.rpccnt[NFSPROC_COMMITDS]);
 	}
 	NFSCL_DEBUG(4, "nfsrpc_commitds: vers=%d minvers=%d\n", vers,
 	    minorvers);
 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
 	txdr_hyper(offset, tl);
 	tl += 2;
 	*tl = txdr_unsigned(cnt);
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, vers, NULL, 1, NULL, &dsp->nfsclds_sess);
 	NFSCL_DEBUG(4, "nfsrpc_commitds: err=%d stat=%d\n", error,
 	    nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		if (vers == NFS_VER3) {
 			error = nfscl_wcc_data(nd, vp, &na, &attrflag, NULL,
 			    NULL);
 			NFSCL_DEBUG(4, "nfsrpc_commitds: wccdata=%d\n", error);
 			if (error != 0)
 				goto nfsmout;
 		}
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF);
 		NFSLOCKDS(dsp);
 		if (NFSBCMP(tl, dsp->nfsclds_verf, NFSX_VERF)) {
 			NFSBCOPY(tl, dsp->nfsclds_verf, NFSX_VERF);
 			error = NFSERR_STALEWRITEVERF;
 		}
 		NFSUNLOCKDS(dsp);
 	}
 nfsmout:
 	if (error == 0 && nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Start up the thread that will execute nfsrpc_commitds().
  */
 static void
 start_commitds(void *arg, int pending)
 {
 	struct nfsclwritedsdorpc *drpc;
 
 	drpc = (struct nfsclwritedsdorpc *)arg;
 	drpc->err = nfsrpc_commitds(drpc->vp, drpc->off, drpc->len,
 	    drpc->dsp, drpc->fhp, drpc->vers, drpc->minorvers, drpc->cred,
 	    drpc->p);
 	drpc->done = 1;
 	crfree(drpc->cred);
 	NFSCL_DEBUG(4, "start_commitds: err=%d\n", drpc->err);
 }
 
 /*
  * Set up the commit DS mirror call for the pNFS I/O thread.
  */
 static int
 nfsio_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp,
     struct nfsfh *fhp, int vers, int minorvers,
     struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
 {
 	int error, ret;
 
 	error = 0;
 	drpc->done = 0;
 	drpc->vp = vp;
 	drpc->off = offset;
 	drpc->len = cnt;
 	drpc->dsp = dsp;
 	drpc->fhp = fhp;
 	drpc->vers = vers;
 	drpc->minorvers = minorvers;
 	drpc->cred = crhold(cred);
 	drpc->p = p;
 	drpc->inprog = 0;
 	ret = EIO;
 	if (nfs_pnfsiothreads != 0) {
 		ret = nfs_pnfsio(start_commitds, drpc);
 		NFSCL_DEBUG(4, "nfsio_commitds: nfs_pnfsio=%d\n", ret);
 	}
 	if (ret != 0) {
 		error = nfsrpc_commitds(vp, offset, cnt, dsp, fhp, vers,
 		    minorvers, cred, p);
 		crfree(drpc->cred);
 	}
 	NFSCL_DEBUG(4, "nfsio_commitds: error=%d\n", error);
 	return (error);
 }
 
 /*
  * NFS Advise rpc
  */
 int
 nfsrpc_advise(vnode_t vp, off_t offset, uint64_t cnt, int advise,
     struct ucred *cred, NFSPROC_T *p)
 {
 	u_int32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	nfsattrbit_t hints;
 	int error;
 
 	NFSZERO_ATTRBIT(&hints);
 	if (advise == POSIX_FADV_WILLNEED)
 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED);
 	else if (advise == POSIX_FADV_DONTNEED)
 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED);
 	else
 		return (0);
 	NFSCL_REQSTART(nd, NFSPROC_IOADVISE, vp, cred);
 	nfsm_stateidtom(nd, NULL, NFSSTATEID_PUTALLZERO);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER);
 	txdr_hyper(offset, tl);
 	tl += 2;
 	txdr_hyper(cnt, tl);
 	nfsrv_putattrbit(nd, &hints);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 #ifdef notyet
 /*
  * NFS advise rpc to a NFSv4.2 DS.
  */
 static int
 nfsrpc_adviseds(vnode_t vp, uint64_t offset, int cnt, int advise,
     struct nfsclds *dsp, struct nfsfh *fhp, int vers, int minorvers,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfssockreq *nrp;
 	nfsattrbit_t hints;
 	int error;
 
 	/* For NFS DSs prior to NFSv4.2, just return OK. */
 	if (vers == NFS_VER3 || minorversion < NFSV42_MINORVERSION)
 		return (0);
 	NFSZERO_ATTRBIT(&hints);
 	if (advise == POSIX_FADV_WILLNEED)
 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_WILLNEED);
 	else if (advise == POSIX_FADV_DONTNEED)
 		NFSSETBIT_ATTRBIT(&hints, NFSV4IOHINT_DONTNEED);
 	else
 		return (0);
 	nd->nd_mrep = NULL;
 	nfscl_reqstart(nd, NFSPROC_IOADVISEDS, nmp, fhp->nfh_fh,
 	    fhp->nfh_len, NULL, &dsp->nfsclds_sess, vers, minorvers, NULL);
 	vers = NFS_VER4;
 	NFSCL_DEBUG(4, "nfsrpc_adviseds: vers=%d minvers=%d\n", vers,
 	    minorvers);
 	nfsm_stateidtom(nd, NULL, NFSSTATEID_PUTALLZERO);
 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
 	txdr_hyper(offset, tl);
 	tl += 2;
 	*tl = txdr_unsigned(cnt);
 	nfsrv_putattrbit(nd, &hints);
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
 		nrp = &nmp->nm_sockreq;
 	error = newnfs_request(nd, nmp, NULL, nrp, vp, p, cred,
 	    NFS_PROG, vers, NULL, 1, NULL, &dsp->nfsclds_sess);
 	NFSCL_DEBUG(4, "nfsrpc_adviseds: err=%d stat=%d\n", error,
 	    nd->nd_repstat);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Start up the thread that will execute nfsrpc_commitds().
  */
 static void
 start_adviseds(void *arg, int pending)
 {
 	struct nfsclwritedsdorpc *drpc;
 
 	drpc = (struct nfsclwritedsdorpc *)arg;
 	drpc->err = nfsrpc_adviseds(drpc->vp, drpc->off, drpc->len,
 	    drpc->advise, drpc->dsp, drpc->fhp, drpc->vers, drpc->minorvers,
 	    drpc->cred, drpc->p);
 	drpc->done = 1;
 	crfree(drpc->cred);
 	NFSCL_DEBUG(4, "start_adviseds: err=%d\n", drpc->err);
 }
 
 /*
  * Set up the advise DS mirror call for the pNFS I/O thread.
  */
 static int
 nfsio_adviseds(vnode_t vp, uint64_t offset, int cnt, int advise,
     struct nfsclds *dsp, struct nfsfh *fhp, int vers, int minorvers,
     struct nfsclwritedsdorpc *drpc, struct ucred *cred, NFSPROC_T *p)
 {
 	int error, ret;
 
 	error = 0;
 	drpc->done = 0;
 	drpc->vp = vp;
 	drpc->off = offset;
 	drpc->len = cnt;
 	drpc->advise = advise;
 	drpc->dsp = dsp;
 	drpc->fhp = fhp;
 	drpc->vers = vers;
 	drpc->minorvers = minorvers;
 	drpc->cred = crhold(cred);
 	drpc->p = p;
 	drpc->inprog = 0;
 	ret = EIO;
 	if (nfs_pnfsiothreads != 0) {
 		ret = nfs_pnfsio(start_adviseds, drpc);
 		NFSCL_DEBUG(4, "nfsio_adviseds: nfs_pnfsio=%d\n", ret);
 	}
 	if (ret != 0) {
 		error = nfsrpc_adviseds(vp, offset, cnt, advise, dsp, fhp, vers,
 		    minorvers, cred, p);
 		crfree(drpc->cred);
 	}
 	NFSCL_DEBUG(4, "nfsio_adviseds: error=%d\n", error);
 	return (error);
 }
 #endif	/* notyet */
 
 /*
  * Do the Allocate operation, retrying for recovery.
  */
 int
 nfsrpc_allocate(vnode_t vp, off_t off, off_t len, struct nfsvattr *nap,
     int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	int error, expireret = 0, retrycnt, nostateid;
 	uint32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsfh *nfhp = NULL;
 	nfsv4stateid_t stateid;
 	off_t tmp_off;
 	void *lckp;
 
 	if (len < 0)
 		return (EINVAL);
 	if (len == 0)
 		return (0);
 	tmp_off = off + len;
 	NFSLOCKMNT(nmp);
 	if (tmp_off > nmp->nm_maxfilesize || tmp_off < off) {
 		NFSUNLOCKMNT(nmp);
 		return (EFBIG);
 	}
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	NFSUNLOCKMNT(nmp);
 	nfhp = VTONFS(vp)->n_fhp;
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		nostateid = 0;
 		nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 		    NFSV4OPEN_ACCESSWRITE, 0, cred, p, &stateid, &lckp);
 		if (stateid.other[0] == 0 && stateid.other[1] == 0 &&
 		    stateid.other[2] == 0) {
 			nostateid = 1;
 			NFSCL_DEBUG(1, "stateid0 in allocate\n");
 		}
 
 		/*
 		 * Not finding a stateid should probably never happen,
 		 * but just return an error for this case.
 		 */
 		if (nostateid != 0)
 			error = EIO;
 		else
 			error = nfsrpc_allocaterpc(vp, off, len, &stateid,
 			    nap, attrflagp, cred, p);
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_allocate");
 		} else if ((error == NFSERR_EXPIRED || (!NFSHASINT(nmp) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev, p);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_DELAY ||
 	    error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	    error == NFSERR_STALEDONTRECOVER ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error != 0 && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 /*
  * The allocate RPC.
  */
 static int
 nfsrpc_allocaterpc(vnode_t vp, off_t off, off_t len, nfsv4stateid_t *stateidp,
     struct nfsvattr *nap, int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_ALLOCATE, vp, cred);
 	nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
 	txdr_hyper(off, tl); tl += 2;
 	txdr_hyper(len, tl); tl += 2;
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = NFS_LATTR_NOSHRINK;
 	} else
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Set up the XDR arguments for the LayoutGet operation.
  */
 static void
 nfsrv_setuplayoutget(struct nfsrv_descript *nd, int iomode, uint64_t offset,
     uint64_t len, uint64_t minlen, nfsv4stateid_t *stateidp, int layouttype,
     int layoutlen, int usecurstateid)
 {
 	uint32_t *tl;
 
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 	    NFSX_STATEID);
 	*tl++ = newnfs_false;		/* Don't signal availability. */
 	*tl++ = txdr_unsigned(layouttype);
 	*tl++ = txdr_unsigned(iomode);
 	txdr_hyper(offset, tl);
 	tl += 2;
 	txdr_hyper(len, tl);
 	tl += 2;
 	txdr_hyper(minlen, tl);
 	tl += 2;
 	if (usecurstateid != 0) {
 		/* Special stateid for Current stateid. */
 		*tl++ = txdr_unsigned(1);
 		*tl++ = 0;
 		*tl++ = 0;
 		*tl++ = 0;
 	} else {
 		*tl++ = txdr_unsigned(stateidp->seqid);
 		NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid);
 		*tl++ = stateidp->other[0];
 		*tl++ = stateidp->other[1];
 		*tl++ = stateidp->other[2];
 	}
 	*tl = txdr_unsigned(layoutlen);
 }
 
 /*
  * Parse the reply for a successful LayoutGet operation.
  */
 static int
 nfsrv_parselayoutget(struct nfsmount *nmp, struct nfsrv_descript *nd,
     nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp)
 {
 	uint32_t *tl;
 	struct nfsclflayout *flp, *prevflp, *tflp;
 	int cnt, error, fhcnt, gotiomode, i, iomode, j, k, l, laytype, nfhlen;
 	int m, mirrorcnt;
 	uint64_t retlen, off;
 	struct nfsfh *nfhp;
 	uint8_t *cp;
 	uid_t user;
 	gid_t grp;
 
 	NFSCL_DEBUG(4, "in nfsrv_parselayoutget\n");
 	error = 0;
 	flp = NULL;
 	gotiomode = -1;
 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID);
 	if (*tl++ != 0)
 		*retonclosep = 1;
 	else
 		*retonclosep = 0;
 	stateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
 	NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep,
 	    (int)stateidp->seqid);
 	stateidp->other[0] = *tl++;
 	stateidp->other[1] = *tl++;
 	stateidp->other[2] = *tl++;
 	cnt = fxdr_unsigned(int, *tl);
 	NFSCL_DEBUG(4, "layg cnt=%d\n", cnt);
 	if (cnt <= 0 || cnt > 10000) {
 		/* Don't accept more than 10000 layouts in reply. */
 		error = NFSERR_BADXDR;
 		goto nfsmout;
 	}
 	for (i = 0; i < cnt; i++) {
 		/* Dissect to the layout type. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER +
 		    3 * NFSX_UNSIGNED);
 		off = fxdr_hyper(tl); tl += 2;
 		retlen = fxdr_hyper(tl); tl += 2;
 		iomode = fxdr_unsigned(int, *tl++);
 		laytype = fxdr_unsigned(int, *tl);
 		NFSCL_DEBUG(4, "layt=%d off=%ju len=%ju iom=%d\n", laytype,
 		    (uintmax_t)off, (uintmax_t)retlen, iomode);
 		/* Ignore length of layout body for now. */
 		if (laytype == NFSLAYOUT_NFSV4_1_FILES) {
 			/* Parse the File layout up to fhcnt. */
 			NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED +
 			    NFSX_HYPER + NFSX_V4DEVICEID);
 			fhcnt = fxdr_unsigned(int, *(tl + 4 +
 			    NFSX_V4DEVICEID / NFSX_UNSIGNED));
 			NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt);
 			if (fhcnt < 0 || fhcnt > 100) {
 				/* Don't accept more than 100 file handles. */
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 			if (fhcnt > 0)
 				flp = malloc(sizeof(*flp) + fhcnt *
 				    sizeof(struct nfsfh *), M_NFSFLAYOUT,
 				    M_WAITOK);
 			else
 				flp = malloc(sizeof(*flp), M_NFSFLAYOUT,
 				    M_WAITOK);
 			flp->nfsfl_flags = NFSFL_FILE;
 			flp->nfsfl_fhcnt = 0;
 			flp->nfsfl_devp = NULL;
 			flp->nfsfl_off = off;
 			if (flp->nfsfl_off + retlen < flp->nfsfl_off)
 				flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off;
 			else
 				flp->nfsfl_end = flp->nfsfl_off + retlen;
 			flp->nfsfl_iomode = iomode;
 			if (gotiomode == -1)
 				gotiomode = flp->nfsfl_iomode;
 			/* Ignore layout body length for now. */
 			NFSBCOPY(tl, flp->nfsfl_dev, NFSX_V4DEVICEID);
 			tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
 			flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++);
 			NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util);
 			mtx_lock(&nmp->nm_mtx);
 			if (nmp->nm_minorvers > 1 && (flp->nfsfl_util &
 			    NFSFLAYUTIL_IOADVISE_THRU_MDS) != 0)
 				nmp->nm_privflag |= NFSMNTP_IOADVISETHRUMDS;
 			mtx_unlock(&nmp->nm_mtx);
 			flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++);
 			flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2;
 			NFSCL_DEBUG(4, "stripe1=%u poff=%ju\n",
 			    flp->nfsfl_stripe1, (uintmax_t)flp->nfsfl_patoff);
 			for (j = 0; j < fhcnt; j++) {
 				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 				nfhlen = fxdr_unsigned(int, *tl);
 				if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) {
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 				nfhp = malloc(sizeof(*nfhp) + nfhlen - 1,
 				    M_NFSFH, M_WAITOK);
 				flp->nfsfl_fh[j] = nfhp;
 				flp->nfsfl_fhcnt++;
 				nfhp->nfh_len = nfhlen;
 				NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen));
 				NFSBCOPY(cp, nfhp->nfh_fh, nfhlen);
 			}
 		} else if (laytype == NFSLAYOUT_FLEXFILE) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED +
 			    NFSX_HYPER);
 			mirrorcnt = fxdr_unsigned(int, *(tl + 2));
 			NFSCL_DEBUG(4, "mirrorcnt=%d\n", mirrorcnt);
 			if (mirrorcnt < 1 || mirrorcnt > NFSDEV_MAXMIRRORS) {
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
 			flp = malloc(sizeof(*flp) + mirrorcnt *
 			    sizeof(struct nfsffm), M_NFSFLAYOUT, M_WAITOK);
 			flp->nfsfl_flags = NFSFL_FLEXFILE;
 			flp->nfsfl_mirrorcnt = mirrorcnt;
 			for (j = 0; j < mirrorcnt; j++)
 				flp->nfsfl_ffm[j].devp = NULL;
 			flp->nfsfl_off = off;
 			if (flp->nfsfl_off + retlen < flp->nfsfl_off)
 				flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off;
 			else
 				flp->nfsfl_end = flp->nfsfl_off + retlen;
 			flp->nfsfl_iomode = iomode;
 			if (gotiomode == -1)
 				gotiomode = flp->nfsfl_iomode;
 			flp->nfsfl_stripeunit = fxdr_hyper(tl);
 			NFSCL_DEBUG(4, "stripeunit=%ju\n",
 			    (uintmax_t)flp->nfsfl_stripeunit);
 			for (j = 0; j < mirrorcnt; j++) {
 				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 				k = fxdr_unsigned(int, *tl);
 				if (k < 1 || k > 128) {
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 				NFSCL_DEBUG(4, "servercnt=%d\n", k);
 				for (l = 0; l < k; l++) {
 					NFSM_DISSECT(tl, uint32_t *,
 					    NFSX_V4DEVICEID + NFSX_STATEID +
 					    2 * NFSX_UNSIGNED);
 					if (l == 0) {
 						/* Just use the first server. */
 						NFSBCOPY(tl,
 						    flp->nfsfl_ffm[j].dev,
 						    NFSX_V4DEVICEID);
 						tl += (NFSX_V4DEVICEID /
 						    NFSX_UNSIGNED);
 						tl++;
 						flp->nfsfl_ffm[j].st.seqid =
 						    *tl++;
 						flp->nfsfl_ffm[j].st.other[0] =
 						    *tl++;
 						flp->nfsfl_ffm[j].st.other[1] =
 						    *tl++;
 						flp->nfsfl_ffm[j].st.other[2] =
 						    *tl++;
 						NFSCL_DEBUG(4, "st.seqid=%u "
 						 "st.o0=0x%x st.o1=0x%x "
 						 "st.o2=0x%x\n",
 						 flp->nfsfl_ffm[j].st.seqid,
 						 flp->nfsfl_ffm[j].st.other[0],
 						 flp->nfsfl_ffm[j].st.other[1],
 						 flp->nfsfl_ffm[j].st.other[2]);
 					} else
 						tl += ((NFSX_V4DEVICEID +
 						    NFSX_STATEID +
 						    NFSX_UNSIGNED) /
 						    NFSX_UNSIGNED);
 					fhcnt = fxdr_unsigned(int, *tl);
 					NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt);
 					if (fhcnt < 1 ||
 					    fhcnt > NFSDEV_MAXVERS) {
 						error = NFSERR_BADXDR;
 						goto nfsmout;
 					}
 					for (m = 0; m < fhcnt; m++) {
 						NFSM_DISSECT(tl, uint32_t *,
 						    NFSX_UNSIGNED);
 						nfhlen = fxdr_unsigned(int,
 						    *tl);
 						NFSCL_DEBUG(4, "nfhlen=%d\n",
 						    nfhlen);
 						if (nfhlen <= 0 || nfhlen >
 						    NFSX_V4FHMAX) {
 							error = NFSERR_BADXDR;
 							goto nfsmout;
 						}
 						NFSM_DISSECT(cp, uint8_t *,
 						    NFSM_RNDUP(nfhlen));
 						if (l == 0) {
 							flp->nfsfl_ffm[j].fhcnt 
 							    = fhcnt;
 							nfhp = malloc(
 							    sizeof(*nfhp) +
 							    nfhlen - 1, M_NFSFH,
 							    M_WAITOK);
 							flp->nfsfl_ffm[j].fh[m]
 							    = nfhp;
 							nfhp->nfh_len = nfhlen;
 							NFSBCOPY(cp,
 							    nfhp->nfh_fh,
 							    nfhlen);
 							NFSCL_DEBUG(4,
 							    "got fh\n");
 						}
 					}
 					/* Now, get the ffsd_user/ffds_group. */
 					error = nfsrv_parseug(nd, 0, &user,
 					    &grp, curthread);
 					NFSCL_DEBUG(4, "after parseu=%d\n",
 					    error);
 					if (error == 0)
 						error = nfsrv_parseug(nd, 1,
 						    &user, &grp, curthread);
 					NFSCL_DEBUG(4, "aft parseg=%d\n",
 					    grp);
 					if (error != 0)
 						goto nfsmout;
 					NFSCL_DEBUG(4, "user=%d group=%d\n",
 					    user, grp);
 					if (l == 0) {
 						flp->nfsfl_ffm[j].user = user;
 						flp->nfsfl_ffm[j].group = grp;
 						NFSCL_DEBUG(4,
 						    "usr=%d grp=%d\n", user,
 						    grp);
 					}
 				}
 			}
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			flp->nfsfl_fflags = fxdr_unsigned(uint32_t, *tl++);
 #ifdef notnow
 			/*
 			 * At this time, there is no flag.
 			 * NFSFLEXFLAG_IOADVISE_THRU_MDS might need to be
 			 * added, or it may never exist?
 			 */
 			mtx_lock(&nmp->nm_mtx);
 			if (nmp->nm_minorvers > 1 && (flp->nfsfl_fflags &
 			    NFSFLEXFLAG_IOADVISE_THRU_MDS) != 0)
 				nmp->nm_privflag |= NFSMNTP_IOADVISETHRUMDS;
 			mtx_unlock(&nmp->nm_mtx);
 #endif
 			flp->nfsfl_statshint = fxdr_unsigned(uint32_t, *tl);
 			NFSCL_DEBUG(4, "fflags=0x%x statshint=%d\n",
 			    flp->nfsfl_fflags, flp->nfsfl_statshint);
 		} else {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		if (flp->nfsfl_iomode == gotiomode) {
 			/* Keep the list in increasing offset order. */
 			tflp = LIST_FIRST(flhp);
 			prevflp = NULL;
 			while (tflp != NULL &&
 			    tflp->nfsfl_off < flp->nfsfl_off) {
 				prevflp = tflp;
 				tflp = LIST_NEXT(tflp, nfsfl_list);
 			}
 			if (prevflp == NULL)
 				LIST_INSERT_HEAD(flhp, flp, nfsfl_list);
 			else
 				LIST_INSERT_AFTER(prevflp, flp,
 				    nfsfl_list);
 			NFSCL_DEBUG(4, "flp inserted\n");
 		} else {
 			printf("nfscl_layoutget(): got wrong iomode\n");
 			nfscl_freeflayout(flp);
 		}
 		flp = NULL;
 	}
 nfsmout:
 	NFSCL_DEBUG(4, "eo nfsrv_parselayoutget=%d\n", error);
 	if (error != 0 && flp != NULL)
 		nfscl_freeflayout(flp);
 	return (error);
 }
 
 /*
  * Parse a user/group digit string.
  */
 static int
 nfsrv_parseug(struct nfsrv_descript *nd, int dogrp, uid_t *uidp, gid_t *gidp,
     NFSPROC_T *p)
 {
 	uint32_t *tl;
 	char *cp, *str, str0[NFSV4_SMALLSTR + 1];
 	uint32_t len = 0;
 	int error = 0;
 
 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 	len = fxdr_unsigned(uint32_t, *tl);
 	str = NULL;
 	if (len > NFSV4_OPAQUELIMIT) {
 		error = NFSERR_BADXDR;
 		goto nfsmout;
 	}
 	NFSCL_DEBUG(4, "nfsrv_parseug: len=%d\n", len);
 	if (len == 0) {
 		if (dogrp != 0)
 			*gidp = GID_NOGROUP;
 		else
 			*uidp = UID_NOBODY;
 		return (0);
 	}
 	if (len > NFSV4_SMALLSTR)
 		str = malloc(len + 1, M_TEMP, M_WAITOK);
 	else
 		str = str0;
 	NFSM_DISSECT(cp, char *, NFSM_RNDUP(len));
 	NFSBCOPY(cp, str, len);
 	str[len] = '\0';
 	NFSCL_DEBUG(4, "nfsrv_parseug: str=%s\n", str);
 	if (dogrp != 0)
 		error = nfsv4_strtogid(nd, str, len, gidp);
 	else
 		error = nfsv4_strtouid(nd, str, len, uidp);
 nfsmout:
 	if (len > NFSV4_SMALLSTR)
 		free(str, M_TEMP);
 	NFSCL_DEBUG(4, "eo nfsrv_parseug=%d\n", error);
 	return (error);
 }
 
 /*
  * Similar to nfsrpc_getlayout(), except that it uses nfsrpc_openlayget(),
  * so that it does both an Open and a Layoutget.
  */
 static int
 nfsrpc_getopenlayout(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,
     int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode,
     struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp,
     struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfscllayout *lyp;
 	struct nfsclflayout *flp;
 	struct nfsclflayouthead flh;
 	int error, islocked, layoutlen, recalled, retonclose, usecurstateid;
 	int layouttype, laystat;
 	nfsv4stateid_t stateid;
 	struct nfsclsession *tsep;
 
 	error = 0;
 	if (NFSHASFLEXFILE(nmp))
 		layouttype = NFSLAYOUT_FLEXFILE;
 	else
 		layouttype = NFSLAYOUT_NFSV4_1_FILES;
 	/*
 	 * If lyp is returned non-NULL, there will be a refcnt (shared lock)
 	 * on it, iff flp != NULL or a lock (exclusive lock) on it iff
 	 * flp == NULL.
 	 */
 	lyp = nfscl_getlayout(nmp->nm_clp, newfhp, newfhlen, 0, mode, &flp,
 	    &recalled);
 	NFSCL_DEBUG(4, "nfsrpc_getopenlayout nfscl_getlayout lyp=%p\n", lyp);
 	if (lyp == NULL)
 		islocked = 0;
 	else if (flp != NULL)
 		islocked = 1;
 	else
 		islocked = 2;
 	if ((lyp == NULL || flp == NULL) && recalled == 0) {
 		LIST_INIT(&flh);
 		tsep = nfsmnt_mdssession(nmp);
 		layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID +
 		    3 * NFSX_UNSIGNED);
 		if (lyp == NULL)
 			usecurstateid = 1;
 		else {
 			usecurstateid = 0;
 			stateid.seqid = lyp->nfsly_stateid.seqid;
 			stateid.other[0] = lyp->nfsly_stateid.other[0];
 			stateid.other[1] = lyp->nfsly_stateid.other[1];
 			stateid.other[2] = lyp->nfsly_stateid.other[2];
 		}
 		error = nfsrpc_openlayoutrpc(nmp, vp, nfhp, fhlen,
 		    newfhp, newfhlen, mode, op, name, namelen,
 		    dpp, &stateid, usecurstateid, layouttype, layoutlen,
 		    &retonclose, &flh, &laystat, cred, p);
 		NFSCL_DEBUG(4, "aft nfsrpc_openlayoutrpc laystat=%d err=%d\n",
 		    laystat, error);
 		laystat = nfsrpc_layoutgetres(nmp, vp, newfhp, newfhlen,
 		    &stateid, retonclose, NULL, &lyp, &flh, layouttype, laystat,
 		    &islocked, cred, p);
 	} else
 		error = nfsrpc_openrpc(nmp, vp, nfhp, fhlen, newfhp, newfhlen,
 		    mode, op, name, namelen, dpp, 0, 0, cred, p, 0, 0);
 	if (islocked == 2)
 		nfscl_rellayout(lyp, 1);
 	else if (islocked == 1)
 		nfscl_rellayout(lyp, 0);
 	return (error);
 }
 
 /*
  * This function does an Open+LayoutGet for an NFSv4.1 mount with pNFS
  * enabled, only for the CLAIM_NULL case.  All other NFSv4 Opens are
  * handled by nfsrpc_openrpc().
  * For the case where op == NULL, dvp is the directory.  When op != NULL, it
  * can be NULL.
  */
 static int
 nfsrpc_openlayoutrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,
     int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode,
     struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp,
     nfsv4stateid_t *stateidp, int usecurstateid, int layouttype,
     int layoutlen, int *retonclosep, struct nfsclflayouthead *flhp,
     int *laystatp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfscldeleg *ndp = NULL;
 	struct nfsvattr nfsva;
 	struct nfsclsession *tsep;
 	uint32_t rflags, deleg;
 	nfsattrbit_t attrbits;
 	int error, ret, acesize, limitby, iomode;
 
 	*dpp = NULL;
 	*laystatp = ENXIO;
 	nfscl_reqstart(nd, NFSPROC_OPENLAYGET, nmp, nfhp, fhlen, NULL, NULL,
 	    0, 0, cred);
 	NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
 	*tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
 	if (NFSHASNFSV4N(nmp)) {
 		*tl = txdr_unsigned(NFSV4OPEN_CLAIMFH);
 	} else {
 		*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
 		nfsm_strtom(nd, name, namelen);
 	}
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSZERO_ATTRBIT(&attrbits);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
 	nfsrv_putattrbit(nd, &attrbits);
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_LAYOUTGET);
 	if ((mode & NFSV4OPEN_ACCESSWRITE) != 0)
 		iomode = NFSLAYOUTIOMODE_RW;
 	else
 		iomode = NFSLAYOUTIOMODE_READ;
 	nfsrv_setuplayoutget(nd, iomode, 0, UINT64_MAX, 0, stateidp,
 	    layouttype, layoutlen, usecurstateid);
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
 	if (error != 0)
 		return (error);
 	NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
 	if (nd->nd_repstat != 0)
 		*laystatp = nd->nd_repstat;
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 		/* ND_NOMOREDATA will be set if the Open operation failed. */
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 		    6 * NFSX_UNSIGNED);
 		op->nfso_stateid.seqid = *tl++;
 		op->nfso_stateid.other[0] = *tl++;
 		op->nfso_stateid.other[1] = *tl++;
 		op->nfso_stateid.other[2] = *tl;
 		rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		if (error != 0)
 			goto nfsmout;
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		deleg = fxdr_unsigned(u_int32_t, *tl);
 		if (deleg == NFSV4OPEN_DELEGATEREAD ||
 		    deleg == NFSV4OPEN_DELEGATEWRITE) {
 			if (!(op->nfso_own->nfsow_clp->nfsc_flags &
 			      NFSCLFLAGS_FIRSTDELEG))
 				op->nfso_own->nfsow_clp->nfsc_flags |=
 				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
 			ndp = malloc(sizeof(struct nfscldeleg) + newfhlen,
 			    M_NFSCLDELEG, M_WAITOK);
 			LIST_INIT(&ndp->nfsdl_owner);
 			LIST_INIT(&ndp->nfsdl_lock);
 			ndp->nfsdl_clp = op->nfso_own->nfsow_clp;
 			ndp->nfsdl_fhlen = newfhlen;
 			NFSBCOPY(newfhp, ndp->nfsdl_fh, newfhlen);
 			newnfs_copyincred(cred, &ndp->nfsdl_cred);
 			nfscl_lockinit(&ndp->nfsdl_rwlock);
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 			    NFSX_UNSIGNED);
 			ndp->nfsdl_stateid.seqid = *tl++;
 			ndp->nfsdl_stateid.other[0] = *tl++;
 			ndp->nfsdl_stateid.other[1] = *tl++;
 			ndp->nfsdl_stateid.other[2] = *tl++;
 			ret = fxdr_unsigned(int, *tl);
 			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
 				ndp->nfsdl_flags = NFSCLDL_WRITE;
 				/*
 				 * Indicates how much the file can grow.
 				 */
 				NFSM_DISSECT(tl, u_int32_t *,
 				    3 * NFSX_UNSIGNED);
 				limitby = fxdr_unsigned(int, *tl++);
 				switch (limitby) {
 				case NFSV4OPEN_LIMITSIZE:
 					ndp->nfsdl_sizelimit = fxdr_hyper(tl);
 					break;
 				case NFSV4OPEN_LIMITBLOCKS:
 					ndp->nfsdl_sizelimit =
 					    fxdr_unsigned(u_int64_t, *tl++);
 					ndp->nfsdl_sizelimit *=
 					    fxdr_unsigned(u_int64_t, *tl);
 					break;
 				default:
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				};
 			} else
 				ndp->nfsdl_flags = NFSCLDL_READ;
 			if (ret != 0)
 				ndp->nfsdl_flags |= NFSCLDL_RECALL;
 			error = nfsrv_dissectace(nd, &ndp->nfsdl_ace, false,
 			    &ret, &acesize, p);
 			if (error != 0)
 				goto nfsmout;
 		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) != 0 ||
 		    nfscl_assumeposixlocks)
 			op->nfso_posixlock = 1;
 		else
 			op->nfso_posixlock = 0;
 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		/* If the 2nd element == NFS_OK, the Getattr succeeded. */
 		if (*++tl == 0) {
 			error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
 			    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
 			    NULL, NULL, NULL, p, cred);
 			if (error != 0)
 				goto nfsmout;
 			if (ndp != NULL) {
 				ndp->nfsdl_change = nfsva.na_filerev;
 				ndp->nfsdl_modtime = nfsva.na_mtime;
 				ndp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 				*dpp = ndp;
 				ndp = NULL;
 			}
 			/*
 			 * At this point, the Open has succeeded, so set
 			 * nd_repstat = NFS_OK.  If the Layoutget failed,
 			 * this function just won't return a layout.
 			 */
 			if (nd->nd_repstat == 0) {
 				NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 				*laystatp = fxdr_unsigned(int, *++tl);
 				if (*laystatp == 0) {
 					error = nfsrv_parselayoutget(nmp, nd,
 					    stateidp, retonclosep, flhp);
 					if (error != 0)
 						*laystatp = error;
 				}
 			} else
 				nd->nd_repstat = 0;	/* Return 0 for Open. */
 		}
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	free(ndp, M_NFSCLDELEG);
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Similar nfsrpc_createv4(), but also does the LayoutGet operation.
  * Used only for mounts with pNFS enabled.
  */
 static int
 nfsrpc_createlayout(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
     int *dattrflagp, int *unlockedp, nfsv4stateid_t *stateidp,
     int usecurstateid, int layouttype, int layoutlen, int *retonclosep,
     struct nfsclflayouthead *flhp, int *laystatp)
 {
 	uint32_t *tl;
 	int error = 0, deleg, newone, ret, acesize, limitby;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	struct nfsclopen *op;
 	struct nfscldeleg *dp = NULL;
 	struct nfsnode *np;
 	struct nfsfh *nfhp;
 	struct nfsclsession *tsep;
 	nfsattrbit_t attrbits;
 	nfsv4stateid_t stateid;
 	struct nfsmount *nmp;
 
 	nmp = VFSTONFS(dvp->v_mount);
 	np = VTONFS(dvp);
 	*laystatp = ENXIO;
 	*unlockedp = 0;
 	*nfhpp = NULL;
 	*dpp = NULL;
 	*attrflagp = 0;
 	*dattrflagp = 0;
 	if (namelen > NFS_MAXNAMLEN)
 		return (ENAMETOOLONG);
 	NFSCL_REQSTART(nd, NFSPROC_CREATELAYGET, dvp, cred);
 	/*
 	 * For V4, this is actually an Open op.
 	 */
 	NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(owp->nfsow_seqid);
 	*tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
 	    NFSV4OPEN_ACCESSREAD);
 	*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
 	*tl = tsep->nfsess_clientid.lval[1];
 	nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
 	if ((fmode & O_EXCL) != 0) {
 		if (NFSHASSESSPERSIST(nmp)) {
 			/* Use GUARDED for persistent sessions. */
 			*tl = txdr_unsigned(NFSCREATE_GUARDED);
 			nfscl_fillsattr(nd, vap, dvp, 0, 0);
 		} else {
 			/* Otherwise, use EXCLUSIVE4_1. */
 			*tl = txdr_unsigned(NFSCREATE_EXCLUSIVE41);
 			NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
 			*tl++ = cverf.lval[0];
 			*tl = cverf.lval[1];
 			nfscl_fillsattr(nd, vap, dvp, 0, 0);
 		}
 	} else {
 		*tl = txdr_unsigned(NFSCREATE_UNCHECKED);
 		nfscl_fillsattr(nd, vap, dvp, 0, 0);
 	}
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
 	nfsm_strtom(nd, name, namelen);
 	/* Get the new file's handle and attributes, plus save the FH. */
 	NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OP_SAVEFH);
 	*tl++ = txdr_unsigned(NFSV4OP_GETFH);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	/* Get the directory's post-op attributes. */
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_PUTFH);
 	(void)nfsm_fhtom(nmp, nd, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	nfsrv_putattrbit(nd, &attrbits);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(NFSV4OP_RESTOREFH);
 	*tl = txdr_unsigned(NFSV4OP_LAYOUTGET);
 	nfsrv_setuplayoutget(nd, NFSLAYOUTIOMODE_RW, 0, UINT64_MAX, 0, stateidp,
 	    layouttype, layoutlen, usecurstateid);
 	error = nfscl_request(nd, dvp, p, cred);
 	if (error != 0)
 		return (error);
 	NFSCL_DEBUG(4, "nfsrpc_createlayout stat=%d err=%d\n", nd->nd_repstat,
 	    error);
 	if (nd->nd_repstat != 0)
 		*laystatp = nd->nd_repstat;
 	NFSCL_INCRSEQID(owp->nfsow_seqid, nd);
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 		NFSCL_DEBUG(4, "nfsrpc_createlayout open succeeded\n");
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 		    6 * NFSX_UNSIGNED);
 		stateid.seqid = *tl++;
 		stateid.other[0] = *tl++;
 		stateid.other[1] = *tl++;
 		stateid.other[2] = *tl;
 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 		if (error != 0)
 			goto nfsmout;
 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 		deleg = fxdr_unsigned(int, *tl);
 		if (deleg == NFSV4OPEN_DELEGATEREAD ||
 		    deleg == NFSV4OPEN_DELEGATEWRITE) {
 			if (!(owp->nfsow_clp->nfsc_flags &
 			      NFSCLFLAGS_FIRSTDELEG))
 				owp->nfsow_clp->nfsc_flags |=
 				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
 			dp = malloc(sizeof(struct nfscldeleg) + NFSX_V4FHMAX,
 			    M_NFSCLDELEG, M_WAITOK);
 			LIST_INIT(&dp->nfsdl_owner);
 			LIST_INIT(&dp->nfsdl_lock);
 			dp->nfsdl_clp = owp->nfsow_clp;
 			newnfs_copyincred(cred, &dp->nfsdl_cred);
 			nfscl_lockinit(&dp->nfsdl_rwlock);
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
 			    NFSX_UNSIGNED);
 			dp->nfsdl_stateid.seqid = *tl++;
 			dp->nfsdl_stateid.other[0] = *tl++;
 			dp->nfsdl_stateid.other[1] = *tl++;
 			dp->nfsdl_stateid.other[2] = *tl++;
 			ret = fxdr_unsigned(int, *tl);
 			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
 				dp->nfsdl_flags = NFSCLDL_WRITE;
 				/*
 				 * Indicates how much the file can grow.
 				 */
 				NFSM_DISSECT(tl, u_int32_t *,
 				    3 * NFSX_UNSIGNED);
 				limitby = fxdr_unsigned(int, *tl++);
 				switch (limitby) {
 				case NFSV4OPEN_LIMITSIZE:
 					dp->nfsdl_sizelimit = fxdr_hyper(tl);
 					break;
 				case NFSV4OPEN_LIMITBLOCKS:
 					dp->nfsdl_sizelimit =
 					    fxdr_unsigned(u_int64_t, *tl++);
 					dp->nfsdl_sizelimit *=
 					    fxdr_unsigned(u_int64_t, *tl);
 					break;
 				default:
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				};
 			} else {
 				dp->nfsdl_flags = NFSCLDL_READ;
 			}
 			if (ret != 0)
 				dp->nfsdl_flags |= NFSCLDL_RECALL;
 			error = nfsrv_dissectace(nd, &dp->nfsdl_ace, false,
 			    &ret, &acesize, p);
 			if (error != 0)
 				goto nfsmout;
 		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 
 		/* Now, we should have the status for the SaveFH. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		if (*++tl == 0) {
 			NFSCL_DEBUG(4, "nfsrpc_createlayout SaveFH ok\n");
 			/*
 			 * Now, process the GetFH and Getattr for the newly
 			 * created file. nfscl_mtofh() will set
 			 * ND_NOMOREDATA if these weren't successful.
 			 */
 			error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
 			NFSCL_DEBUG(4, "aft nfscl_mtofh err=%d\n", error);
 			if (error != 0)
 				goto nfsmout;
 		} else
 			nd->nd_flag |= ND_NOMOREDATA;
 		/* Now we have the PutFH and Getattr for the directory. */
 		if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			if (*++tl != 0)
 				nd->nd_flag |= ND_NOMOREDATA;
 			else {
 				NFSM_DISSECT(tl, uint32_t *, 2 *
 				    NFSX_UNSIGNED);
 				if (*++tl != 0)
 					nd->nd_flag |= ND_NOMOREDATA;
 			}
 		}
 		if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 			/* Load the directory attributes. */
 			error = nfsm_loadattr(nd, dnap);
 			NFSCL_DEBUG(4, "aft nfsm_loadattr err=%d\n", error);
 			if (error != 0)
 				goto nfsmout;
 			*dattrflagp = 1;
 			if (dp != NULL && *attrflagp != 0) {
 				dp->nfsdl_change = nnap->na_filerev;
 				dp->nfsdl_modtime = nnap->na_mtime;
 				dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
 			}
 			/*
 			 * We can now complete the Open state.
 			 */
 			nfhp = *nfhpp;
 			if (dp != NULL) {
 				dp->nfsdl_fhlen = nfhp->nfh_len;
 				NFSBCOPY(nfhp->nfh_fh, dp->nfsdl_fh,
 				    nfhp->nfh_len);
 			}
 			/*
 			 * Get an Open structure that will be
 			 * attached to the OpenOwner, acquired already.
 			 */
 			error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len, 
 			    (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
 			    cred, p, NULL, &op, &newone, NULL, 0, false);
 			if (error != 0)
 				goto nfsmout;
 			op->nfso_stateid = stateid;
 			newnfs_copyincred(cred, &op->nfso_cred);
 
 			nfscl_openrelease(nmp, op, error, newone);
 			*unlockedp = 1;
 
 			/* Now, handle the RestoreFH and LayoutGet. */
 			if (nd->nd_repstat == 0) {
 				NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 				*laystatp = fxdr_unsigned(int, *(tl + 3));
 				if (*laystatp == 0) {
 					error = nfsrv_parselayoutget(nmp, nd,
 					    stateidp, retonclosep, flhp);
 					if (error != 0)
 						*laystatp = error;
 				}
 				NFSCL_DEBUG(4, "aft nfsrv_parselayout err=%d\n",
 				    error);
 			} else
 				nd->nd_repstat = 0;
 		}
 	}
 	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 	if (error == NFSERR_STALECLIENTID)
 		nfscl_initiate_recovery(owp->nfsow_clp);
 nfsmout:
 	NFSCL_DEBUG(4, "eo nfsrpc_createlayout err=%d\n", error);
 	if (error == 0)
 		*dpp = dp;
 	else
 		free(dp, M_NFSCLDELEG);
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Similar to nfsrpc_getopenlayout(), except that it used for the Create case.
  */
 static int
 nfsrpc_getcreatelayout(vnode_t dvp, char *name, int namelen, struct vattr *vap,
     nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
     struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
     struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
     int *dattrflagp, int *unlockedp)
 {
 	struct nfscllayout *lyp;
 	struct nfsclflayouthead flh;
 	struct nfsfh *nfhp;
 	struct nfsclsession *tsep;
 	struct nfsmount *nmp;
 	nfsv4stateid_t stateid;
 	int error, layoutlen, layouttype, retonclose, laystat;
 
 	error = 0;
 	nmp = VFSTONFS(dvp->v_mount);
 	if (NFSHASFLEXFILE(nmp))
 		layouttype = NFSLAYOUT_FLEXFILE;
 	else
 		layouttype = NFSLAYOUT_NFSV4_1_FILES;
 	LIST_INIT(&flh);
 	tsep = nfsmnt_mdssession(nmp);
 	layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID + 3 * NFSX_UNSIGNED);
 	error = nfsrpc_createlayout(dvp, name, namelen, vap, cverf, fmode,
 	    owp, dpp, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp,
 	    unlockedp, &stateid, 1, layouttype, layoutlen, &retonclose,
 	    &flh, &laystat);
 	NFSCL_DEBUG(4, "aft nfsrpc_createlayoutrpc laystat=%d err=%d\n",
 	    laystat, error);
 	lyp = NULL;
 	if (laystat == 0) {
 		nfhp = *nfhpp;
 		laystat = nfsrpc_layoutgetres(nmp, dvp, nfhp->nfh_fh,
 		    nfhp->nfh_len, &stateid, retonclose, NULL, &lyp, &flh,
 		    layouttype, laystat, NULL, cred, p);
 	} else
 		laystat = nfsrpc_layoutgetres(nmp, dvp, NULL, 0, &stateid,
 		    retonclose, NULL, &lyp, &flh, layouttype, laystat, NULL,
 		    cred, p);
 	if (laystat == 0)
 		nfscl_rellayout(lyp, 0);
 	return (error);
 }
 
 /*
  * Process the results of a layoutget() operation.
  */
 static int
 nfsrpc_layoutgetres(struct nfsmount *nmp, vnode_t vp, uint8_t *newfhp,
     int newfhlen, nfsv4stateid_t *stateidp, int retonclose, uint32_t *notifybit,
     struct nfscllayout **lypp, struct nfsclflayouthead *flhp, int layouttype,
     int laystat, int *islockedp, struct ucred *cred, NFSPROC_T *p)
 {
 	struct nfsclflayout *tflp;
 	struct nfscldevinfo *dip;
 	uint8_t *dev;
 	int i, mirrorcnt;
 
 	if (laystat == NFSERR_UNKNLAYOUTTYPE) {
 		NFSLOCKMNT(nmp);
 		if (!NFSHASFLEXFILE(nmp)) {
 			/* Switch to using Flex File Layout. */
 			nmp->nm_state |= NFSSTA_FLEXFILE;
 		} else if (layouttype == NFSLAYOUT_FLEXFILE) {
 			/* Disable pNFS. */
 			NFSCL_DEBUG(1, "disable PNFS\n");
 			nmp->nm_state &= ~(NFSSTA_PNFS | NFSSTA_FLEXFILE);
 		}
 		NFSUNLOCKMNT(nmp);
 	}
 	if (laystat == 0) {
 		NFSCL_DEBUG(4, "nfsrpc_layoutgetres at FOREACH\n");
 		LIST_FOREACH(tflp, flhp, nfsfl_list) {
 			if (layouttype == NFSLAYOUT_FLEXFILE)
 				mirrorcnt = tflp->nfsfl_mirrorcnt;
 			else
 				mirrorcnt = 1;
 			for (i = 0; i < mirrorcnt; i++) {
 				laystat = nfscl_adddevinfo(nmp, NULL, i, tflp);
 				NFSCL_DEBUG(4, "aft adddev=%d\n", laystat);
 				if (laystat != 0) {
 					if (layouttype == NFSLAYOUT_FLEXFILE)
 						dev = tflp->nfsfl_ffm[i].dev;
 					else
 						dev = tflp->nfsfl_dev;
 					laystat = nfsrpc_getdeviceinfo(nmp, dev,
 					    layouttype, notifybit, &dip, cred,
 					    p);
 					NFSCL_DEBUG(4, "aft nfsrpc_gdi=%d\n",
 					    laystat);
 					if (laystat != 0)
 						goto out;
 					laystat = nfscl_adddevinfo(nmp, dip, i,
 					    tflp);
 					if (laystat != 0)
 						printf("nfsrpc_layoutgetresout"
 						    ": cannot add\n");
 				}
 			}
 		}
 	}
 out:
 	if (laystat == 0) {
 		/*
 		 * nfscl_layout() always returns with the nfsly_lock
 		 * set to a refcnt (shared lock).
 		 * Passing in dvp is sufficient, since it is only used to
 		 * get the fsid for the file system.
 		 */
 		laystat = nfscl_layout(nmp, vp, newfhp, newfhlen, stateidp,
 		    layouttype, retonclose, flhp, lypp, cred, p);
 		NFSCL_DEBUG(4, "nfsrpc_layoutgetres: aft nfscl_layout=%d\n",
 		    laystat);
 		if (laystat == 0 && islockedp != NULL)
 			*islockedp = 1;
 	}
 	return (laystat);
 }
 
 /*
  * nfs copy_file_range operation.
  */
 int
 nfsrpc_copy_file_range(vnode_t invp, off_t *inoffp, vnode_t outvp,
     off_t *outoffp, size_t *lenp, unsigned int flags, int *inattrflagp,
     struct nfsvattr *innap, int *outattrflagp, struct nfsvattr *outnap,
     struct ucred *cred, bool consecutive, bool *must_commitp)
 {
 	int commit, error, expireret = 0, retrycnt;
 	u_int32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(invp->v_mount);
 	struct nfsfh *innfhp = NULL, *outnfhp = NULL;
 	nfsv4stateid_t instateid, outstateid;
 	void *inlckp, *outlckp;
 
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	innfhp = VTONFS(invp)->n_fhp;
 	outnfhp = VTONFS(outvp)->n_fhp;
 	retrycnt = 0;
 	do {
 		/* Get both stateids. */
 		inlckp = NULL;
 		nfscl_getstateid(invp, innfhp->nfh_fh, innfhp->nfh_len,
 		    NFSV4OPEN_ACCESSREAD, 0, NULL, curthread, &instateid,
 		    &inlckp);
 		outlckp = NULL;
 		nfscl_getstateid(outvp, outnfhp->nfh_fh, outnfhp->nfh_len,
 		    NFSV4OPEN_ACCESSWRITE, 0, NULL, curthread, &outstateid,
 		    &outlckp);
 
 		error = nfsrpc_copyrpc(invp, *inoffp, outvp, *outoffp, lenp,
 		    &instateid, &outstateid, innap, inattrflagp, outnap,
 		    outattrflagp, consecutive, &commit, cred, curthread);
 		if (error == 0) {
 			if (commit != NFSWRITE_FILESYNC)
 				*must_commitp = true;
 			*inoffp += *lenp;
 			*outoffp += *lenp;
 		} else if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (inlckp != NULL)
 			nfscl_lockderef(inlckp);
 		if (outlckp != NULL)
 			nfscl_lockderef(outlckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_cfr");
 		} else if ((error == NFSERR_EXPIRED || (!NFSHASINT(nmp) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev,
 			    curthread);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_DELAY ||
 	    error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4));
 	if (error != 0 && (retrycnt >= 4 ||
 	    error == NFSERR_STALESTATEID || error == NFSERR_BADSESSION ||
 	      error == NFSERR_STALEDONTRECOVER))
 		error = EIO;
 	return (error);
 }
 
 /*
  * The copy RPC.
  */
 static int
 nfsrpc_copyrpc(vnode_t invp, off_t inoff, vnode_t outvp, off_t outoff,
     size_t *lenp, nfsv4stateid_t *instateidp, nfsv4stateid_t *outstateidp,
     struct nfsvattr *innap, int *inattrflagp, struct nfsvattr *outnap,
     int *outattrflagp, bool consecutive, int *commitp, struct ucred *cred,
     NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct nfsmount *nmp;
 	nfsattrbit_t attrbits;
 	struct vattr va;
 	uint64_t len;
 
 	nmp = VFSTONFS(outvp->v_mount);
 	*inattrflagp = *outattrflagp = 0;
 	*commitp = NFSWRITE_UNSTABLE;
 	len = *lenp;
 	*lenp = 0;
 	if (len > nfs_maxcopyrange)
 		len = nfs_maxcopyrange;
 	NFSCL_REQSTART(nd, NFSPROC_COPY, invp, cred);
 	/*
 	 * First do a Setattr of atime to the server's clock
 	 * time.  The FreeBSD "collective" was of the opinion
 	 * that setting atime was necessary for this syscall.
 	 * Do the Setattr before the Copy, so that it can be
 	 * handled well if the server replies NFSERR_DELAY to
 	 * the Setattr operation.
 	 */
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_SETATTR);
 	nfsm_stateidtom(nd, instateidp, NFSSTATEID_PUTSTATEID);
 	VATTR_NULL(&va);
 	va.va_atime.tv_sec = va.va_atime.tv_nsec = 0;
 	va.va_vaflags = VA_UTIMES_NULL;
 	nfscl_fillsattr(nd, &va, invp, 0, 0);
 
 	/* Now Getattr the invp attributes. */
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 
 	/* Set outvp. */
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_PUTFH);
 	(void)nfsm_fhtom(nmp, nd, VTONFS(outvp)->n_fhp->nfh_fh,
 	    VTONFS(outvp)->n_fhp->nfh_len, 0);
 
 	/* Do the Copy. */
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_COPY);
 	nfsm_stateidtom(nd, instateidp, NFSSTATEID_PUTSTATEID);
 	nfsm_stateidtom(nd, outstateidp, NFSSTATEID_PUTSTATEID);
 	NFSM_BUILD(tl, uint32_t *, 3 * NFSX_HYPER + 4 * NFSX_UNSIGNED);
 	txdr_hyper(inoff, tl); tl += 2;
 	txdr_hyper(outoff, tl); tl += 2;
 	txdr_hyper(len, tl); tl += 2;
 	if (consecutive)
 		*tl++ = newnfs_true;
 	else
 		*tl++ = newnfs_false;
 	*tl++ = newnfs_true;
 	*tl++ = 0;
 
 	/* Get the outvp attributes. */
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSWRITEGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 
 	error = nfscl_request(nd, invp, p, cred);
 	if (error != 0)
 		return (error);
 	/* Skip over the Setattr reply. */
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		if (*(tl + 1) == 0) {
 			error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
 			if (error != 0)
 				goto nfsmout;
 		} else
 			nd->nd_flag |= ND_NOMOREDATA;
 	}
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 		/* Get the input file's attributes. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		if (*(tl + 1) == 0) {
 			error = nfsm_loadattr(nd, innap);
 			if (error != 0)
 				goto nfsmout;
 			*inattrflagp = 1;
 		} else
 			nd->nd_flag |= ND_NOMOREDATA;
 	}
 	/* Skip over return stat for PutFH. */
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		if (*++tl != 0)
 			nd->nd_flag |= ND_NOMOREDATA;
 	}
 	/* Skip over return stat for Copy. */
 	if ((nd->nd_flag & ND_NOMOREDATA) == 0)
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		if (*tl != 0) {
 			/* There should be no callback ids. */
 			error = NFSERR_BADXDR;
 			goto nfsmout;
 		}
 		NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + 3 * NFSX_UNSIGNED +
 		    NFSX_VERF);
 		len = fxdr_hyper(tl); tl += 2;
 		*commitp = fxdr_unsigned(int, *tl++);
 		NFSLOCKMNT(nmp);
 		if (!NFSHASWRITEVERF(nmp)) {
 			NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 			NFSSETWRITEVERF(nmp);
 	    	} else if (NFSBCMP(tl, nmp->nm_verf, NFSX_VERF)) {
 			NFSBCOPY(tl, nmp->nm_verf, NFSX_VERF);
 			nd->nd_repstat = NFSERR_STALEWRITEVERF;
 		}
 		NFSUNLOCKMNT(nmp);
 		tl += (NFSX_VERF / NFSX_UNSIGNED);
 		if (nd->nd_repstat == 0 && *++tl != newnfs_true)
 			/* Must be a synchronous copy. */
 			nd->nd_repstat = NFSERR_NOTSUPP;
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, outnap);
 		if (error == 0)
 			*outattrflagp = NFS_LATTR_NOSHRINK;
 		if (nd->nd_repstat == 0)
 			*lenp = len;
 	} else if (nd->nd_repstat == NFSERR_OFFLOADNOREQS) {
 		/*
 		 * For the case where consecutive is not supported, but
 		 * synchronous is supported, we can try consecutive == false
 		 * by returning this error.  Otherwise, return NFSERR_NOTSUPP,
 		 * since Copy cannot be done.
 		 */
 		if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 			if (!consecutive || *++tl == newnfs_false)
 				nd->nd_repstat = NFSERR_NOTSUPP;
 		} else
 			nd->nd_repstat = NFSERR_BADXDR;
 	}
 	if (error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Seek operation.
  */
 int
 nfsrpc_seek(vnode_t vp, off_t *offp, bool *eofp, int content,
     struct ucred *cred, struct nfsvattr *nap, int *attrflagp)
 {
 	int error, expireret = 0, retrycnt;
 	u_int32_t clidrev = 0;
 	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 	struct nfsnode *np = VTONFS(vp);
 	struct nfsfh *nfhp = NULL;
 	nfsv4stateid_t stateid;
 	void *lckp;
 
 	if (nmp->nm_clp != NULL)
 		clidrev = nmp->nm_clp->nfsc_clientidrev;
 	nfhp = np->n_fhp;
 	retrycnt = 0;
 	do {
 		lckp = NULL;
 		nfscl_getstateid(vp, nfhp->nfh_fh, nfhp->nfh_len,
 		    NFSV4OPEN_ACCESSREAD, 0, cred, curthread, &stateid, &lckp);
 		error = nfsrpc_seekrpc(vp, offp, &stateid, eofp, content,
 		    nap, attrflagp, cred);
 		if (error == NFSERR_STALESTATEID)
 			nfscl_initiate_recovery(nmp->nm_clp);
 		if (lckp != NULL)
 			nfscl_lockderef(lckp);
 		if (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 		    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 		    error == NFSERR_OLDSTATEID || error == NFSERR_BADSESSION) {
 			(void) nfs_catnap(PZERO, error, "nfs_seek");
 		} else if ((error == NFSERR_EXPIRED || (!NFSHASINT(nmp) &&
 		    error == NFSERR_BADSTATEID)) && clidrev != 0) {
 			expireret = nfscl_hasexpired(nmp->nm_clp, clidrev,
 			    curthread);
 		} else if (error == NFSERR_BADSTATEID && NFSHASINT(nmp)) {
 			error = EIO;
 		}
 		retrycnt++;
 	} while (error == NFSERR_GRACE || error == NFSERR_STALESTATEID ||
 	    error == NFSERR_STALEDONTRECOVER || error == NFSERR_DELAY ||
 	    error == NFSERR_BADSESSION ||
 	    (error == NFSERR_OLDSTATEID && retrycnt < 20) ||
 	    ((error == NFSERR_EXPIRED || error == NFSERR_BADSTATEID) &&
 	     expireret == 0 && clidrev != 0 && retrycnt < 4) ||
 	    (error == NFSERR_OPENMODE && retrycnt < 4));
 	if (error && retrycnt >= 4)
 		error = EIO;
 	return (error);
 }
 
 /*
  * The seek RPC.
  */
 static int
 nfsrpc_seekrpc(vnode_t vp, off_t *offp, nfsv4stateid_t *stateidp, bool *eofp,
     int content, struct nfsvattr *nap, int *attrflagp, struct ucred *cred)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_SEEK, vp, cred);
 	nfsm_stateidtom(nd, stateidp, NFSSTATEID_PUTSTATEID);
 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
 	txdr_hyper(*offp, tl); tl += 2;
 	*tl++ = txdr_unsigned(content);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, curthread, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED + NFSX_HYPER);
 		if (*tl++ == newnfs_true)
 			*eofp = true;
 		else
 			*eofp = false;
 		*offp = fxdr_hyper(tl);
 		/* Just skip over Getattr op status. */
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = 1;
 	}
 	error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The getextattr RPC.
  */
 int
 nfsrpc_getextattr(vnode_t vp, const char *name, struct uio *uiop, ssize_t *lenp,
     struct nfsvattr *nap, int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	uint32_t len, len2;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_GETEXTATTR, vp, cred);
 	nfsm_strtom(nd, name, strlen(name));
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 		len = fxdr_unsigned(uint32_t, *tl);
 		/* Sanity check lengths. */
 		if (uiop != NULL && len > 0 && len <= IOSIZE_MAX &&
 		    uiop->uio_resid <= UINT32_MAX) {
 			len2 = uiop->uio_resid;
 			if (len2 >= len)
 				error = nfsm_mbufuio(nd, uiop, len);
 			else {
 				error = nfsm_mbufuio(nd, uiop, len2);
 				if (error == 0) {
 					/*
 					 * nfsm_mbufuio() advances to a multiple
 					 * of 4, so round up len2 as well.  Then
 					 * we need to advance over the rest of
 					 * the data, rounding up the remaining
 					 * length.
 					 */
 					len2 = NFSM_RNDUP(len2);
 					len2 = NFSM_RNDUP(len - len2);
 					if (len2 > 0)
 						error = nfsm_advance(nd, len2,
 						    -1);
 				}
 			}
 		} else if (uiop == NULL && len > 0) {
 			/* Just wants the length and not the data. */
 			error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 		} else if (len > 0)
 			error = ENOATTR;
 		if (error != 0)
 			goto nfsmout;
 		*lenp = len;
 		/* Just skip over Getattr op status. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = 1;
 	}
 	if (error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The setextattr RPC.
  */
 int
 nfsrpc_setextattr(vnode_t vp, const char *name, struct uio *uiop,
     struct nfsvattr *nap, int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_SETEXTATTR, vp, cred);
 	if (uiop->uio_resid > nd->nd_maxreq) {
 		/* nd_maxreq is set by NFSCL_REQSTART(). */
 		m_freem(nd->nd_mreq);
 		return (EINVAL);
 	}
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4SXATTR_EITHER);
 	nfsm_strtom(nd, name, strlen(name));
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(uiop->uio_resid);
 	nfsm_uiombuf(nd, uiop, uiop->uio_resid);
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		/* Just skip over the reply and Getattr op status. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + 3 *
 		    NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = 1;
 	}
 	if (error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The removeextattr RPC.
  */
 int
 nfsrpc_rmextattr(vnode_t vp, const char *name, struct nfsvattr *nap,
     int *attrflagp, struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int error;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_RMEXTATTR, vp, cred);
 	nfsm_strtom(nd, name, strlen(name));
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
 		/* Just skip over the reply and Getattr op status. */
 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_HYPER + 3 *
 		    NFSX_UNSIGNED);
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = 1;
 	}
 	if (error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * The listextattr RPC.
  */
 int
 nfsrpc_listextattr(vnode_t vp, uint64_t *cookiep, struct uio *uiop,
     size_t *lenp, bool *eofp, struct nfsvattr *nap, int *attrflagp,
     struct ucred *cred, NFSPROC_T *p)
 {
 	uint32_t *tl;
 	int cnt, error, i, len;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	nfsattrbit_t attrbits;
 	u_char c;
 
 	*attrflagp = 0;
 	NFSCL_REQSTART(nd, NFSPROC_LISTEXTATTR, vp, cred);
 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
 	txdr_hyper(*cookiep, tl); tl += 2;
 	*tl++ = txdr_unsigned(*lenp);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
 	nfsrv_putattrbit(nd, &attrbits);
 	error = nfscl_request(nd, vp, p, cred);
 	if (error != 0)
 		return (error);
 	*eofp = true;
 	*lenp = 0;
 	if (nd->nd_repstat == 0) {
 		NFSM_DISSECT(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
 		*cookiep = fxdr_hyper(tl); tl += 2;
 		cnt = fxdr_unsigned(int, *tl);
 		if (cnt < 0) {
 			error = EBADRPC;
 			goto nfsmout;
 		}
 		for (i = 0; i < cnt; i++) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			len = fxdr_unsigned(int, *tl);
 			if (len <= 0 || len > EXTATTR_MAXNAMELEN) {
 				error = EBADRPC;
 				goto nfsmout;
 			}
 			if (uiop == NULL)
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 			else if (uiop->uio_resid >= len + 1) {
 				c = len;
 				error = uiomove(&c, sizeof(c), uiop);
 				if (error == 0)
 					error = nfsm_mbufuio(nd, uiop, len);
 			} else {
 				error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 				*eofp = false;
 			}
 			if (error != 0)
 				goto nfsmout;
 			*lenp += (len + 1);
 		}
 		/* Get the eof and skip over the Getattr op status. */
 		NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
 		/*
 		 * *eofp is set false above, because it wasn't able to copy
 		 * all of the reply.
 		 */
 		if (*eofp && *tl == 0)
 			*eofp = false;
 		error = nfsm_loadattr(nd, nap);
 		if (error == 0)
 			*attrflagp = 1;
 	}
 	if (error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	m_freem(nd->nd_mrep);
 	return (error);
 }
 
 /*
  * Split an mbuf list.  For non-M_EXTPG mbufs, just use m_split().
  */
 static struct mbuf *
 nfsm_split(struct mbuf *mp, uint64_t xfer)
 {
 	struct mbuf *m, *m2;
 	vm_page_t pg;
 	int i, j, left, pgno, plen, trim;
 	char *cp, *cp2;
 
 	if ((mp->m_flags & M_EXTPG) == 0) {
 		m = m_split(mp, xfer, M_WAITOK);
 		return (m);
 	}
 
 	/* Find the correct mbuf to split at. */
 	for (m = mp; m != NULL && xfer > m->m_len; m = m->m_next)
 		xfer -= m->m_len;
 	if (m == NULL)
 		return (NULL);
 
 	/* If xfer == m->m_len, we can just split the mbuf list. */
 	if (xfer == m->m_len) {
 		m2 = m->m_next;
 		m->m_next = NULL;
 		return (m2);
 	}
 
 	/* Find the page to split at. */
 	pgno = 0;
 	left = xfer;
 	do {
 		if (pgno == 0)
 			plen = m_epg_pagelen(m, 0, m->m_epg_1st_off);
 		else
 			plen = m_epg_pagelen(m, pgno, 0);
 		if (left <= plen)
 			break;
 		left -= plen;
 		pgno++;
 	} while (pgno < m->m_epg_npgs);
 	if (pgno == m->m_epg_npgs)
 		panic("nfsm_split: eroneous ext_pgs mbuf");
 
 	m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs);
 	m2->m_epg_flags |= EPG_FLAG_ANON;
 
 	/*
 	 * If left < plen, allocate a new page for the new mbuf
 	 * and copy the data after left in the page to this new
 	 * page.
 	 */
 	if (left < plen) {
 		pg = vm_page_alloc_noobj(VM_ALLOC_WAITOK | VM_ALLOC_NODUMP |
 		    VM_ALLOC_WIRED);
 		m2->m_epg_pa[0] = VM_PAGE_TO_PHYS(pg);
 		m2->m_epg_npgs = 1;
 
 		/* Copy the data after left to the new page. */
 		trim = plen - left;
 		cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]);
 		if (pgno == 0)
 			cp += m->m_epg_1st_off;
 		cp += left;
 		cp2 = (char *)(void *)PHYS_TO_DMAP(m2->m_epg_pa[0]);
 		if (pgno == m->m_epg_npgs - 1)
 			m2->m_epg_last_len = trim;
 		else {
 			cp2 += PAGE_SIZE - trim;
 			m2->m_epg_1st_off = PAGE_SIZE - trim;
 			m2->m_epg_last_len = m->m_epg_last_len;
 		}
 		memcpy(cp2, cp, trim);
 		m2->m_len = trim;
 	} else {
 		m2->m_len = 0;
 		m2->m_epg_last_len = m->m_epg_last_len;
 	}
 
 	/* Move the pages beyond pgno to the new mbuf. */
 	for (i = pgno + 1, j = m2->m_epg_npgs; i < m->m_epg_npgs; i++, j++) {
 		m2->m_epg_pa[j] = m->m_epg_pa[i];
 		/* Never moves page 0. */
 		m2->m_len += m_epg_pagelen(m, i, 0);
 	}
 	m2->m_epg_npgs = j;
 	m->m_epg_npgs = pgno + 1;
 	m->m_epg_last_len = left;
 	m->m_len = xfer;
 
 	m2->m_next = m->m_next;
 	m->m_next = NULL;
 	return (m2);
 }
 
 /*
  * Do the NFSv4.1 Bind Connection to Session.
  * Called from the reconnect layer of the krpc (sys/rpc/clnt_rc.c).
  */
 void
 nfsrpc_bindconnsess(CLIENT *cl, void *arg, struct ucred *cr)
 {
 	struct nfscl_reconarg *rcp = (struct nfscl_reconarg *)arg;
 	uint32_t res, *tl;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
 	struct rpc_callextra ext;
 	struct timeval utimeout;
 	enum clnt_stat stat;
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_BINDCONNTOSESS, NULL, NULL, 0, NULL, NULL,
 	    NFS_VER4, rcp->minorvers, NULL);
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
 	memcpy(tl, rcp->sessionid, NFSX_V4SESSIONID);
 	tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
 	*tl++ = txdr_unsigned(NFSCDFC4_FORE_OR_BOTH);
 	*tl = newnfs_false;
 
 	memset(&ext, 0, sizeof(ext));
 	utimeout.tv_sec = 30;
 	utimeout.tv_usec = 0;
 	ext.rc_auth = authunix_create(cr);
 	nd->nd_mrep = NULL;
 	stat = CLNT_CALL_MBUF(cl, &ext, NFSV4PROC_COMPOUND, nd->nd_mreq,
 	    &nd->nd_mrep, utimeout);
 	AUTH_DESTROY(ext.rc_auth);
 	if (stat != RPC_SUCCESS) {
 		printf("nfsrpc_bindconnsess: call failed stat=%d\n", stat);
 		return;
 	}
 	if (nd->nd_mrep == NULL) {
 		printf("nfsrpc_bindconnsess: no reply args\n");
 		return;
 	}
 	error = 0;
 	newnfs_realign(&nd->nd_mrep, M_WAITOK);
 	nd->nd_md = nd->nd_mrep;
 	nd->nd_dpos = mtod(nd->nd_md, char *);
 	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	nd->nd_repstat = fxdr_unsigned(uint32_t, *tl++);
 	if (nd->nd_repstat == NFSERR_OK) {
 		res = fxdr_unsigned(uint32_t, *tl);
 		if (res > 0 && (error = nfsm_advance(nd, NFSM_RNDUP(res),
 		    -1)) != 0)
 			goto nfsmout;
 		NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID +
 		    4 * NFSX_UNSIGNED);
 		tl += 3;
 		if (!NFSBCMP(tl, rcp->sessionid, NFSX_V4SESSIONID)) {
 			tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
 			res = fxdr_unsigned(uint32_t, *tl);
 			if (res != NFSCDFS4_BOTH)
 				printf("nfsrpc_bindconnsess: did not "
 				    "return FS4_BOTH\n");
 		} else
 			printf("nfsrpc_bindconnsess: not same "
 			    "sessionid\n");
 	} else if (nd->nd_repstat != NFSERR_BADSESSION)
 		printf("nfsrpc_bindconnsess: returned %d\n", nd->nd_repstat);
 nfsmout:
 	if (error != 0)
 		printf("nfsrpc_bindconnsess: reply bad xdr\n");
 	m_freem(nd->nd_mrep);
 }
 
 /*
  * Do roughly what nfs_statfs() does for NFSv4, but when called with a shared
  * locked vnode.
  */
 static void
 nfscl_statfs(struct vnode *vp, struct ucred *cred, NFSPROC_T *td)
 {
 	struct nfsvattr nfsva;
 	struct nfsfsinfo fs;
 	struct nfsstatfs sb;
 	struct mount *mp;
 	struct nfsmount *nmp;
 	uint32_t lease;
 	int attrflag, error;
 
 	mp = vp->v_mount;
 	nmp = VFSTONFS(mp);
 	error = nfsrpc_statfs(vp, &sb, &fs, &lease, cred, td, &nfsva,
 	    &attrflag);
 	if (attrflag != 0)
 		(void) nfscl_loadattrcache(&vp, &nfsva, NULL, 0, 1);
 	if (error == 0) {
 		NFSLOCKCLSTATE();
 		if (nmp->nm_clp != NULL)
 			nmp->nm_clp->nfsc_renew = NFSCL_RENEW(lease);
 		NFSUNLOCKCLSTATE();
 		mtx_lock(&nmp->nm_mtx);
 		nfscl_loadfsinfo(nmp, &fs);
 		nfscl_loadsbinfo(nmp, &sb, &mp->mnt_stat);
 		mp->mnt_stat.f_iosize = newnfs_iosize(nmp);
 		mtx_unlock(&nmp->nm_mtx);
 	}
 }
diff --git a/sys/kgssapi/gss_impl.c b/sys/kgssapi/gss_impl.c
index 2bb785b63345..ae37cb646f1f 100644
--- a/sys/kgssapi/gss_impl.c
+++ b/sys/kgssapi/gss_impl.c
@@ -1,366 +1,368 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
  * Authors: Doug Rabson <dfr@rabson.org>
  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/kobj.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/syscall.h>
 #include <sys/sysent.h>
 #include <sys/sysproto.h>
 
 #include <kgssapi/gssapi.h>
 #include <kgssapi/gssapi_impl.h>
 #include <rpc/rpc.h>
 #include <rpc/rpc_com.h>
 #include <rpc/rpcsec_gss.h>
 
 #include "gssd.h"
 #include "kgss_if.h"
 
 MALLOC_DEFINE(M_GSSAPI, "GSS-API", "GSS-API");
 
 /*
  * Syscall hooks
  */
 static struct syscall_helper_data gssd_syscalls[] = {
 	SYSCALL_INIT_HELPER(gssd_syscall),
 	SYSCALL_INIT_LAST
 };
 
 struct kgss_mech_list kgss_mechs;
 struct mtx kgss_gssd_lock;
 
 KGSS_VNET_DEFINE(CLIENT *, kgss_gssd_handle) = NULL;
 
 static int
 kgss_load(void)
 {
 	int error;
 
 	LIST_INIT(&kgss_mechs);
 	error = syscall_helper_register(gssd_syscalls, SY_THR_STATIC_KLD);
 	if (error != 0)
 		return (error);
 	return (0);
 }
 
 static void
 kgss_unload(void)
 {
 
 	syscall_helper_unregister(gssd_syscalls);
 }
 
 int
 sys_gssd_syscall(struct thread *td, struct gssd_syscall_args *uap)
 {
         struct sockaddr_un sun;
         struct netconfig *nconf;
 	char path[MAXPATHLEN];
 	int error;
 	CLIENT *cl, *oldcl;
         
 	error = priv_check(td, PRIV_NFS_DAEMON);
 	if (error)
 		return (error);
 
 	error = copyinstr(uap->path, path, sizeof(path), NULL);
 	if (error)
 		return (error);
 	if (strlen(path) + 1 > sizeof(sun.sun_path))
 		return (EINVAL);
 
 	if (path[0] != '\0') {
 		sun.sun_family = AF_LOCAL;
 		strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
 		sun.sun_len = SUN_LEN(&sun);
 		
 		nconf = getnetconfigent("local");
 		cl = clnt_reconnect_create(nconf,
 		    (struct sockaddr *) &sun, GSSD, GSSDVERS,
 		    RPC_MAXDATASIZE, RPC_MAXDATASIZE);
 		/*
 		 * The number of retries defaults to INT_MAX, which effectively
 		 * means an infinite, uninterruptable loop.  Limiting it to
 		 * five retries keeps it from running forever.
 		 */
 		if (cl != NULL) {
 			int retry_count = 5;
 			struct timeval timo;
 			CLNT_CONTROL(cl, CLSET_RETRIES, &retry_count);
 
 			/*
 			 * Set the timeout for an upcall to 5 minutes.  The
 			 * default of 25 seconds is not long enough for some
 			 * gss_XXX() calls done by the gssd(8) daemon.
 			 */
 			timo.tv_sec = 5 * 60;
 			timo.tv_usec = 0;
 			CLNT_CONTROL(cl, CLSET_TIMEOUT, &timo);
 		}
 	} else
 		cl = NULL;
 
 	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
 	mtx_lock(&kgss_gssd_lock);
 	oldcl = KGSS_VNET(kgss_gssd_handle);
 	KGSS_VNET(kgss_gssd_handle) = cl;
 	mtx_unlock(&kgss_gssd_lock);
 	KGSS_CURVNET_RESTORE();
 
 	if (oldcl != NULL) {
 		CLNT_CLOSE(oldcl);
 		CLNT_RELEASE(oldcl);
 	}
 
 	return (0);
 }
 
 int
 kgss_oid_equal(const gss_OID oid1, const gss_OID oid2)
 {
 
 	if (oid1 == oid2)
 		return (1);
 	if (!oid1 || !oid2)
 		return (0);
 	if (oid1->length != oid2->length)
 		return (0);
 	if (memcmp(oid1->elements, oid2->elements, oid1->length))
 		return (0);
 	return (1);
 }
 
 void
 kgss_install_mech(gss_OID mech_type, const char *name, struct kobj_class *cls)
 {
 	struct kgss_mech *km;
 
 	km = malloc(sizeof(struct kgss_mech), M_GSSAPI, M_WAITOK);
 	km->km_mech_type = mech_type;
 	km->km_mech_name = name;
 	km->km_class = cls;
 	LIST_INSERT_HEAD(&kgss_mechs, km, km_link);
 }
 
 void
 kgss_uninstall_mech(gss_OID mech_type)
 {
 	struct kgss_mech *km;
 
 	LIST_FOREACH(km, &kgss_mechs, km_link) {
 		if (kgss_oid_equal(km->km_mech_type, mech_type)) {
 			LIST_REMOVE(km, km_link);
 			free(km, M_GSSAPI);
 			return;
 		}
 	}
 }
 
 gss_OID
 kgss_find_mech_by_name(const char *name)
 {
 	struct kgss_mech *km;
 
 	LIST_FOREACH(km, &kgss_mechs, km_link) {
 		if (!strcmp(km->km_mech_name, name)) {
 			return (km->km_mech_type);
 		}
 	}
 	return (GSS_C_NO_OID);
 }
 
 const char *
 kgss_find_mech_by_oid(const gss_OID oid)
 {
 	struct kgss_mech *km;
 
 	LIST_FOREACH(km, &kgss_mechs, km_link) {
 		if (kgss_oid_equal(km->km_mech_type, oid)) {
 			return (km->km_mech_name);
 		}
 	}
 	return (NULL);
 }
 
 gss_ctx_id_t
 kgss_create_context(gss_OID mech_type)
 {
 	struct kgss_mech *km;
 	gss_ctx_id_t ctx;
 
 	LIST_FOREACH(km, &kgss_mechs, km_link) {
 		if (kgss_oid_equal(km->km_mech_type, mech_type))
 			break;
 	}
 	if (!km)
 		return (NULL);
 
 	ctx = (gss_ctx_id_t) kobj_create(km->km_class, M_GSSAPI, M_WAITOK);
 	KGSS_INIT(ctx);
 
 	return (ctx);
 }
 
 void
 kgss_delete_context(gss_ctx_id_t ctx, gss_buffer_t output_token)
 {
 
 	KGSS_DELETE(ctx, output_token);
 	kobj_delete((kobj_t) ctx, M_GSSAPI);
 }
 
 OM_uint32
 kgss_transfer_context(gss_ctx_id_t ctx)
 {
 	struct export_sec_context_res res;
 	struct export_sec_context_args args;
 	enum clnt_stat stat;
 	OM_uint32 maj_stat;
 
 	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
 	if (!KGSS_VNET(kgss_gssd_handle)) {
 		KGSS_CURVNET_RESTORE();
 		return (GSS_S_FAILURE);
 	}
 
 	args.ctx = ctx->handle;
 	bzero(&res, sizeof(res));
 	stat = gssd_export_sec_context_1(&args, &res, KGSS_VNET(kgss_gssd_handle));
 	KGSS_CURVNET_RESTORE();
 	if (stat != RPC_SUCCESS) {
 		return (GSS_S_FAILURE);
 	}
 
 	maj_stat = KGSS_IMPORT(ctx, res.format, &res.interprocess_token);
 	ctx->handle = 0;
 
 	xdr_free((xdrproc_t) xdr_export_sec_context_res, &res);
 
 	return (maj_stat);
 }
 
 void
 kgss_copy_buffer(const gss_buffer_t from, gss_buffer_t to)
 {
 	to->length = from->length;
 	if (from->length) {
 		to->value = malloc(from->length, M_GSSAPI, M_WAITOK);
 		bcopy(from->value, to->value, from->length);
 	} else {
 		to->value = NULL;
 	}
 }
 
 /*
  * Acquire the kgss_gssd_handle and return it with a reference count,
  * if it is available.
  */
 CLIENT *
 kgss_gssd_client(void)
 {
 	CLIENT *cl;
 
 	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
 	mtx_lock(&kgss_gssd_lock);
 	cl = KGSS_VNET(kgss_gssd_handle);
 	if (cl != NULL)
 		CLNT_ACQUIRE(cl);
 	mtx_unlock(&kgss_gssd_lock);
 	KGSS_CURVNET_RESTORE();
 	return (cl);
 }
 
 /*
  * Kernel module glue
  */
 static int
 kgssapi_modevent(module_t mod, int type, void *data)
 {
 	int error = 0;
 
 	switch (type) {
 	case MOD_LOAD:
 		rpc_gss_entries.rpc_gss_refresh_auth = rpc_gss_refresh_auth;
 		rpc_gss_entries.rpc_gss_secfind = rpc_gss_secfind;
 		rpc_gss_entries.rpc_gss_secpurge = rpc_gss_secpurge;
 		rpc_gss_entries.rpc_gss_seccreate = rpc_gss_seccreate;
 		rpc_gss_entries.rpc_gss_set_defaults = rpc_gss_set_defaults;
 		rpc_gss_entries.rpc_gss_max_data_length =
 		    rpc_gss_max_data_length;
 		rpc_gss_entries.rpc_gss_get_error = rpc_gss_get_error;
 		rpc_gss_entries.rpc_gss_mech_to_oid = rpc_gss_mech_to_oid;
 		rpc_gss_entries.rpc_gss_oid_to_mech = rpc_gss_oid_to_mech;
 		rpc_gss_entries.rpc_gss_qop_to_num = rpc_gss_qop_to_num;
 		rpc_gss_entries.rpc_gss_get_mechanisms = rpc_gss_get_mechanisms;
 		rpc_gss_entries.rpc_gss_get_versions = rpc_gss_get_versions;
 		rpc_gss_entries.rpc_gss_is_installed = rpc_gss_is_installed;
 		rpc_gss_entries.rpc_gss_set_svc_name = rpc_gss_set_svc_name;
 		rpc_gss_entries.rpc_gss_clear_svc_name = rpc_gss_clear_svc_name;
 		rpc_gss_entries.rpc_gss_getcred = rpc_gss_getcred;
 		rpc_gss_entries.rpc_gss_set_callback = rpc_gss_set_callback;
 		rpc_gss_entries.rpc_gss_clear_callback = rpc_gss_clear_callback;
 		rpc_gss_entries.rpc_gss_get_principal_name =
 		    rpc_gss_get_principal_name;
 		rpc_gss_entries.rpc_gss_svc_max_data_length =
 		    rpc_gss_svc_max_data_length;
+		rpc_gss_entries.rpc_gss_ip_to_srv_principal =
+		    rpc_gss_ip_to_srv_principal;
 		mtx_init(&kgss_gssd_lock, "kgss_gssd_lock", NULL, MTX_DEF);
 		error = kgss_load();
 		break;
 	case MOD_UNLOAD:
 		kgss_unload();
 		mtx_destroy(&kgss_gssd_lock);
 		/*
 		 * Unloading of the kgssapi module is not currently supported.
 		 * If somebody wants this, we would need to keep track of
 		 * currently executing threads and make sure the count is 0.
 		 */
 		/* FALLTHROUGH */
 	default:
 		error = EOPNOTSUPP;
 	}
 	return (error);
 }
 static moduledata_t kgssapi_mod = {
 	"kgssapi",
 	kgssapi_modevent,
 	NULL,
 };
 DECLARE_MODULE(kgssapi, kgssapi_mod, SI_SUB_VFS, SI_ORDER_ANY);
 MODULE_DEPEND(kgssapi, xdr, 1, 1, 1);
 MODULE_DEPEND(kgssapi, krpc, 1, 1, 1);
 MODULE_VERSION(kgssapi, 1);
diff --git a/sys/kgssapi/gssapi.h b/sys/kgssapi/gssapi.h
index ef9181bf1251..37cc8a1a5a09 100644
--- a/sys/kgssapi/gssapi.h
+++ b/sys/kgssapi/gssapi.h
@@ -1,617 +1,635 @@
 /*
  * Copyright (C) The Internet Society (2000).  All Rights Reserved.
  *
  * This document and translations of it may be copied and furnished to
  * others, and derivative works that comment on or otherwise explain it
  * or assist in its implementation may be prepared, copied, published
  * and distributed, in whole or in part, without restriction of any
  * kind, provided that the above copyright notice and this paragraph are
  * included on all such copies and derivative works.  However, this
  * document itself may not be modified in any way, such as by removing
  * the copyright notice or references to the Internet Society or other
  * Internet organizations, except as needed for the purpose of
  * developing Internet standards in which case the procedures for
  * copyrights defined in the Internet Standards process must be
  * followed, or as required to translate it into languages other than
  * English.
  *
  * The limited permissions granted above are perpetual and will not be
  * revoked by the Internet Society or its successors or assigns.
  *
  * This document and the information contained herein is provided on an
  * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
  * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
  * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
  * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  */
 
 #ifndef _KGSSAPI_GSSAPI_H_
 #define _KGSSAPI_GSSAPI_H_
 
 /*
  * A cut-down version of the GSS-API for in-kernel use
  */
 
 /*
  * Now define the three implementation-dependent types.
  */
 typedef struct _gss_ctx_id_t *gss_ctx_id_t;
 typedef struct _gss_cred_id_t *gss_cred_id_t;
 typedef struct _gss_name_t *gss_name_t;
 
 /*
  * We can't use X/Open definitions, so roll our own.
  */
 typedef uint32_t OM_uint32;
 typedef uint64_t OM_uint64;
 
 typedef struct gss_OID_desc_struct {
   OM_uint32 length;
   void      *elements;
 } gss_OID_desc, *gss_OID;
 
 typedef struct gss_OID_set_desc_struct  {
   size_t     count;
   gss_OID    elements;
 } gss_OID_set_desc, *gss_OID_set;
 
 typedef struct gss_buffer_desc_struct {
   size_t length;
   void *value;
 } gss_buffer_desc, *gss_buffer_t;
 
 typedef struct gss_channel_bindings_struct {
   OM_uint32 initiator_addrtype;
   gss_buffer_desc initiator_address;
   OM_uint32 acceptor_addrtype;
   gss_buffer_desc acceptor_address;
   gss_buffer_desc application_data;
 } *gss_channel_bindings_t;
 
 /*
  * For now, define a QOP-type as an OM_uint32
  */
 typedef OM_uint32 gss_qop_t;
 
 typedef int gss_cred_usage_t;
 
 /*
  * Flag bits for context-level services.
  */
 #define GSS_C_DELEG_FLAG      1
 #define GSS_C_MUTUAL_FLAG     2
 #define GSS_C_REPLAY_FLAG     4
 #define GSS_C_SEQUENCE_FLAG   8
 #define GSS_C_CONF_FLAG       16
 #define GSS_C_INTEG_FLAG      32
 #define GSS_C_ANON_FLAG       64
 #define GSS_C_PROT_READY_FLAG 128
 #define GSS_C_TRANS_FLAG      256
 
 /*
  * Credential usage options
  */
 #define GSS_C_BOTH     0
 #define GSS_C_INITIATE 1
 #define GSS_C_ACCEPT   2
 
 /*
  * Status code types for gss_display_status
  */
 #define GSS_C_GSS_CODE  1
 #define GSS_C_MECH_CODE 2
 
 /*
  * The constant definitions for channel-bindings address families
  */
 #define GSS_C_AF_UNSPEC     0
 #define GSS_C_AF_LOCAL      1
 #define GSS_C_AF_INET       2
 #define GSS_C_AF_IMPLINK    3
 #define GSS_C_AF_PUP        4
 #define GSS_C_AF_CHAOS      5
 #define GSS_C_AF_NS         6
 #define GSS_C_AF_NBS        7
 #define GSS_C_AF_ECMA       8
 #define GSS_C_AF_DATAKIT    9
 #define GSS_C_AF_CCITT      10
 #define GSS_C_AF_SNA        11
 #define GSS_C_AF_DECnet     12
 #define GSS_C_AF_DLI        13
 #define GSS_C_AF_LAT        14
 #define GSS_C_AF_HYLINK     15
 #define GSS_C_AF_APPLETALK  16
 #define GSS_C_AF_BSC        17
 #define GSS_C_AF_DSS        18
 #define GSS_C_AF_OSI        19
 #define GSS_C_AF_X25        21
 #define GSS_C_AF_NULLADDR   255
 
 /*
  * Various Null values
  */
 #define GSS_C_NO_NAME ((gss_name_t) 0)
 #define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
 #define GSS_C_NO_OID ((gss_OID) 0)
 #define GSS_C_NO_OID_SET ((gss_OID_set) 0)
 #define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
 #define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
 #define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
 #define GSS_C_EMPTY_BUFFER {0, NULL}
 
 /*
  * Some alternate names for a couple of the above
  * values.  These are defined for V1 compatibility.
  */
 #define GSS_C_NULL_OID GSS_C_NO_OID
 #define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET
 
 /*
  * Define the default Quality of Protection for per-message
  * services.  Note that an implementation that offers multiple
  * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero
  * (as done here) to mean "default protection", or to a specific
  * explicit QOP value.  However, a value of 0 should always be
  * interpreted by a GSS-API implementation as a request for the
  * default protection level.
  */
 #define GSS_C_QOP_DEFAULT 0
 
 /*
  * Expiration time of 2^32-1 seconds means infinite lifetime for a
  * credential or security context
  */
 #define GSS_C_INDEFINITE 0xfffffffful
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
  * "\x01\x02\x01\x01"},
  * corresponding to an object-identifier value of
  * {iso(1) member-body(2) United States(840) mit(113554)
  * infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant
  * GSS_C_NT_USER_NAME should be initialized to point
  * to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_USER_NAME;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
  *              "\x01\x02\x01\x02"},
  * corresponding to an object-identifier value of
  * {iso(1) member-body(2) United States(840) mit(113554)
  * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
  * The constant GSS_C_NT_MACHINE_UID_NAME should be
  * initialized to point to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_MACHINE_UID_NAME;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
  *              "\x01\x02\x01\x03"},
  * corresponding to an object-identifier value of
  * {iso(1) member-body(2) United States(840) mit(113554)
  * infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
  * The constant GSS_C_NT_STRING_UID_NAME should be
  * initialized to point to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_STRING_UID_NAME;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
  * corresponding to an object-identifier value of
  * {iso(1) org(3) dod(6) internet(1) security(5)
  * nametypes(6) gss-host-based-services(2)).  The constant
  * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point
  * to that gss_OID_desc.  This is a deprecated OID value, and
  * implementations wishing to support hostbased-service names
  * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID,
  * defined below, to identify such names;
  * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym
  * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input
  * parameter, but should not be emitted by GSS-API
  * implementations
  */
 extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
  *              "\x01\x02\x01\x04"}, corresponding to an
  * object-identifier value of {iso(1) member-body(2)
  * Unites States(840) mit(113554) infosys(1) gssapi(2)
  * generic(1) service_name(4)}.  The constant
  * GSS_C_NT_HOSTBASED_SERVICE should be initialized
  * to point to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {6, (void *)"\x2b\x06\01\x05\x06\x03"},
  * corresponding to an object identifier value of
  * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
  * 6(nametypes), 3(gss-anonymous-name)}.  The constant
  * and GSS_C_NT_ANONYMOUS should be initialized to point
  * to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_ANONYMOUS;
 
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
  * {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
  * corresponding to an object-identifier value of
  * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
  * 6(nametypes), 4(gss-api-exported-name)}.  The constant
  * GSS_C_NT_EXPORT_NAME should be initialized to point
  * to that gss_OID_desc.
  */
 extern gss_OID GSS_C_NT_EXPORT_NAME;
 
 /*
  *   This name form shall be represented by the Object Identifier {iso(1)
  *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
  *   krb5(2) krb5_name(1)}.  The recommended symbolic name for this type
  *   is "GSS_KRB5_NT_PRINCIPAL_NAME".
  */
 extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
 
 /*
  * This name form shall be represented by the Object Identifier {iso(1)
  * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
  * generic(1) user_name(1)}.  The recommended symbolic name for this
  * type is "GSS_KRB5_NT_USER_NAME".
  */
 extern gss_OID GSS_KRB5_NT_USER_NAME;
 
 /*
  * This name form shall be represented by the Object Identifier {iso(1)
  * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
  * generic(1) machine_uid_name(2)}.  The recommended symbolic name for
  * this type is "GSS_KRB5_NT_MACHINE_UID_NAME".
  */
 extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME;
 
 /*
  * This name form shall be represented by the Object Identifier {iso(1)
  * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
  * generic(1) string_uid_name(3)}.  The recommended symbolic name for
  * this type is "GSS_KRB5_NT_STRING_UID_NAME".
  */
 extern gss_OID GSS_KRB5_NT_STRING_UID_NAME;
 
 /* Major status codes */
 
 #define GSS_S_COMPLETE 0
 
 /*
  * Some "helper" definitions to make the status code macros obvious.
  */
 #define GSS_C_CALLING_ERROR_OFFSET 24
 #define GSS_C_ROUTINE_ERROR_OFFSET 16
 #define GSS_C_SUPPLEMENTARY_OFFSET 0
 #define GSS_C_CALLING_ERROR_MASK 0377ul
 #define GSS_C_ROUTINE_ERROR_MASK 0377ul
 #define GSS_C_SUPPLEMENTARY_MASK 0177777ul
 
 /*
  * The macros that test status codes for error conditions.
  * Note that the GSS_ERROR() macro has changed slightly from
  * the V1 GSS-API so that it now evaluates its argument
  * only once.
  */
 #define GSS_CALLING_ERROR(x) \
  (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
 #define GSS_ROUTINE_ERROR(x) \
  (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
 #define GSS_SUPPLEMENTARY_INFO(x) \
  (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
 #define GSS_ERROR(x) \
  (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
        (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
 
 /*
  * Now the actual status code definitions
  */
 
 /*
  * Calling errors:
  */
 #define GSS_S_CALL_INACCESSIBLE_READ \
 (1ul << GSS_C_CALLING_ERROR_OFFSET)
 #define GSS_S_CALL_INACCESSIBLE_WRITE \
 (2ul << GSS_C_CALLING_ERROR_OFFSET)
 #define GSS_S_CALL_BAD_STRUCTURE \
 (3ul << GSS_C_CALLING_ERROR_OFFSET)
 
 /*
  * Routine errors:
  */
 #define GSS_S_BAD_MECH             (1ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_NAME             (2ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_NAMETYPE         (3ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_BINDINGS         (4ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_STATUS           (5ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_SIG              (6ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_MIC		   GSS_S_BAD_SIG
 #define GSS_S_NO_CRED              (7ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_NO_CONTEXT           (8ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_DEFECTIVE_TOKEN      (9ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_CREDENTIALS_EXPIRED  (11ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_CONTEXT_EXPIRED      (12ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_FAILURE              (13ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_BAD_QOP              (14ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_UNAUTHORIZED         (15ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_UNAVAILABLE          (16ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_DUPLICATE_ELEMENT    (17ul << GSS_C_ROUTINE_ERROR_OFFSET)
 #define GSS_S_NAME_NOT_MN          (18ul << GSS_C_ROUTINE_ERROR_OFFSET)
 
 /*
  * Supplementary info bits:
  */
 #define GSS_S_CONTINUE_NEEDED \
 	 (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
 #define GSS_S_DUPLICATE_TOKEN \
 	 (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
 #define GSS_S_OLD_TOKEN \
 	 (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
 #define GSS_S_UNSEQ_TOKEN \
 	 (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
 #define GSS_S_GAP_TOKEN \
 	 (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
 
+/*
+ * NI_MAXSERV and NI_MAXHOST.  The srv_principal argument for
+ * rpc_gss_ip_to_srv_principal should point to at least
+ * NI_MAXSERV + NI_MAXHOST + 1 bytes of storage. The "+ 1" is for the '@'.
+ * The NI_MAXHOST limit is checked for gss_ip_to_dns().
+ * These should be set to the same value as they are in <netdb.h>.
+ */
+#ifndef NI_MAXHOST
+#define	NI_MAXSERV	32
+#define	NI_MAXHOST	1025
+#endif
+
 __BEGIN_DECLS
 
 /*
  * Finally, function prototypes for the GSS-API routines.
  */
 OM_uint32 gss_acquire_cred
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_name_t,       /* desired_name */
 	       OM_uint32,              /* time_req */
 	       const gss_OID_set,      /* desired_mechs */
 	       gss_cred_usage_t,       /* cred_usage */
 	       gss_cred_id_t *,        /* output_cred_handle */
 	       gss_OID_set *,          /* actual_mechs */
 	       OM_uint32 *             /* time_rec */
 	      );
 
 OM_uint32 gss_release_cred
 	      (OM_uint32 *,            /* minor_status */
 	       gss_cred_id_t *         /* cred_handle */
 	      );
 
 OM_uint32 gss_init_sec_context
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_cred_id_t,    /* initiator_cred_handle */
 	       gss_ctx_id_t *,         /* context_handle */
 	       const gss_name_t,       /* target_name */
 	       const gss_OID,          /* mech_type */
 	       OM_uint32,              /* req_flags */
 	       OM_uint32,              /* time_req */
 	       const gss_channel_bindings_t,
 				       /* input_chan_bindings */
 	       const gss_buffer_t,     /* input_token */
 	       gss_OID *,              /* actual_mech_type */
 	       gss_buffer_t,           /* output_token */
 	       OM_uint32 *,            /* ret_flags */
 	       OM_uint32 *             /* time_rec */
 	      );
 
 OM_uint32 gss_accept_sec_context
 	      (OM_uint32 *,            /* minor_status */
 	       gss_ctx_id_t *,         /* context_handle */
 	       const gss_cred_id_t,    /* acceptor_cred_handle */
 	       const gss_buffer_t,     /* input_token_buffer */
 	       const gss_channel_bindings_t,
 				       /* input_chan_bindings */
 	       gss_name_t *,           /* src_name */
 	       gss_OID *,              /* mech_type */
 	       gss_buffer_t,           /* output_token */
 	       OM_uint32 *,            /* ret_flags */
 	       OM_uint32 *,            /* time_rec */
 	       gss_cred_id_t *         /* delegated_cred_handle */
 	      );
 
 OM_uint32 gss_delete_sec_context
 	      (OM_uint32 *,            /* minor_status */
 	       gss_ctx_id_t *,         /* context_handle */
 	       gss_buffer_t            /* output_token */
 	      );
 
 OM_uint32 gss_get_mic
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       gss_qop_t,              /* qop_req */
 	       const gss_buffer_t,     /* message_buffer */
 	       gss_buffer_t            /* message_token */
 	      );
 
 OM_uint32 gss_verify_mic
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       const gss_buffer_t,     /* message_buffer */
 	       const gss_buffer_t,     /* token_buffer */
 	       gss_qop_t *             /* qop_state */
 	      );
 
 OM_uint32 gss_wrap
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       int,                    /* conf_req_flag */
 	       gss_qop_t,              /* qop_req */
 	       const gss_buffer_t,     /* input_message_buffer */
 	       int *,                  /* conf_state */
 	       gss_buffer_t            /* output_message_buffer */
 	      );
 
 OM_uint32 gss_unwrap
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       const gss_buffer_t,     /* input_message_buffer */
 	       gss_buffer_t,           /* output_message_buffer */
 	       int *,                  /* conf_state */
 	       gss_qop_t *             /* qop_state */
 	      );
 
 OM_uint32 gss_display_status
 	      (OM_uint32 *,            /* minor_status */
 	       OM_uint32,              /* status_value */
 	       int,                    /* status_type */
 	       const gss_OID,          /* mech_type */
 	       OM_uint32 *,            /* message_context */
 	       gss_buffer_t            /* status_string */
 	      );
 
 OM_uint32 gss_import_name
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_buffer_t,     /* input_name_buffer */
 	       const gss_OID,          /* input_name_type */
 	       gss_name_t *            /* output_name */
 	      );
 
 OM_uint32 gss_export_name
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_name_t,       /* input_name */
 	       gss_buffer_t            /* exported_name */
 	      );
 
 OM_uint32 gss_release_name
 	      (OM_uint32 *,            /* minor_status */
 	       gss_name_t *            /* input_name */
 	      );
 
 OM_uint32 gss_release_buffer
 	      (OM_uint32 *,            /* minor_status */
 	       gss_buffer_t            /* buffer */
 	      );
 
 OM_uint32 gss_release_oid_set
 	      (OM_uint32 *,            /* minor_status */
 	       gss_OID_set *           /* set */
 	      );
 
 OM_uint32 gss_wrap_size_limit (
 	       OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       int,                    /* conf_req_flag */
 	       gss_qop_t,              /* qop_req */
 	       OM_uint32,              /* req_output_size */
 	       OM_uint32 *             /* max_input_size */
 	      );
 
 OM_uint32 gss_create_empty_oid_set (
 	       OM_uint32 *,            /* minor_status */
 	       gss_OID_set *           /* oid_set */
 	      );
 
 OM_uint32 gss_add_oid_set_member (
 	       OM_uint32 *,            /* minor_status */
 	       const gss_OID,          /* member_oid */
 	       gss_OID_set *           /* oid_set */
 	      );
 
 OM_uint32 gss_test_oid_set_member (
 	       OM_uint32 *,            /* minor_status */
 	       const gss_OID,          /* member */
 	       const gss_OID_set,      /* set */
 	       int *                   /* present */
 	      );
 
 OM_uint32 gss_canonicalize_name (
 	       OM_uint32 *,            /* minor_status */
 	       const gss_name_t,       /* input_name */
 	       const gss_OID,          /* mech_type */
 	       gss_name_t *            /* output_name */
 	      );
 
 /*
  * Other extensions and helper functions.
  */
 
 OM_uint32 gss_set_cred_option
 	      (OM_uint32 *,		/* minor status */
 	       gss_cred_id_t *,		/* cred */
 	       const gss_OID,		/* option to set */
 	       const gss_buffer_t	/* option value */
 	      );
 
 OM_uint32 gss_pname_to_uid
 	      (OM_uint32 *,		/* minor status */
 	       const gss_name_t pname,	/* principal name */
 	       const gss_OID mech,	/* mechanism to query */
 	       uid_t *uidp		/* pointer to UID for result */
 	      );
 
 /*
  * On entry, *numgroups is set to the maximum number of groups to return. On exit, *numgroups is set to the actual number of groups returned.
  */
 OM_uint32 gss_pname_to_unix_cred
 	      (OM_uint32 *,		/* minor status */
 	       const gss_name_t pname,	/* principal name */
 	       const gss_OID mech,	/* mechanism to query */
 	       uid_t *uidp,		/* pointer to UID for result */
 	       gid_t *gidp,		/* pointer to GID for result */
 	       int *numgroups,		/* number of groups */
 	       gid_t *groups		/* pointer to group list */
 	      );
 
+OM_uint32 gss_ip_to_dns
+	      (OM_uint32 *,		/* minor status */
+	       char *ip_addr,	/* IP host address string */
+	       char *dns_name		/* pointer to dns_name for result */
+	      );
+
 /*
  * Mbuf oriented message signing and encryption.
  *
  * Get_mic allocates an mbuf to hold the message checksum. Verify_mic
  * may modify the passed-in mic but will not free it.
  *
  * Wrap and unwrap
  * consume the message and generate a new mbuf chain with the
  * result. The original message is freed on error.
  */
 struct mbuf;
 OM_uint32 gss_get_mic_mbuf
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       gss_qop_t,              /* qop_req */
 	       struct mbuf *,          /* message_buffer */
 	       struct mbuf **          /* message_token */
 	      );
 
 OM_uint32 gss_verify_mic_mbuf
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       struct mbuf *,          /* message_buffer */
 	       struct mbuf *,          /* token_buffer */
 	       gss_qop_t *             /* qop_state */
 	      );
 
 OM_uint32 gss_wrap_mbuf
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       int,                    /* conf_req_flag */
 	       gss_qop_t,              /* qop_req */
 	       struct mbuf **,         /* message_buffer */
 	       int *                   /* conf_state */
 	      );
 
 OM_uint32 gss_unwrap_mbuf
 	      (OM_uint32 *,            /* minor_status */
 	       const gss_ctx_id_t,     /* context_handle */
 	       struct mbuf **,         /* message_buffer */
 	       int *,                  /* conf_state */
 	       gss_qop_t *             /* qop_state */
 	      );
 
 __END_DECLS
 
 #endif /* _KGSSAPI_GSSAPI_H_ */
diff --git a/sys/kgssapi/gssd.x b/sys/kgssapi/gssd.x
index 29503ac8599f..b50f39b33554 100644
--- a/sys/kgssapi/gssd.x
+++ b/sys/kgssapi/gssd.x
@@ -1,264 +1,278 @@
 /*-
  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
  * Authors: Doug Rabson <dfr@rabson.org>
  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 
 #ifdef RPC_HDR
 
 %#ifdef _KERNEL
 %#include <kgssapi/gssapi.h>
 %#else
 %#include <gssapi/gssapi.h>
+%#include <netdb.h>
 %#endif
 
 %extern bool_t xdr_gss_buffer_desc(XDR *xdrs, gss_buffer_desc *buf);
 %extern bool_t xdr_gss_OID_desc(XDR *xdrs, gss_OID_desc *oid);
 %extern bool_t xdr_gss_OID(XDR *xdrs, gss_OID *oidp);
 %extern bool_t xdr_gss_OID_set_desc(XDR *xdrs, gss_OID_set_desc *set);
 %extern bool_t xdr_gss_OID_set(XDR *xdrs, gss_OID_set *setp);
 %extern bool_t xdr_gss_channel_bindings_t(XDR *xdrs, gss_channel_bindings_t *chp);
 
 #endif
 
 typedef uint64_t gssd_ctx_id_t;
 typedef uint64_t gssd_cred_id_t;
 typedef uint64_t gssd_name_t;
 
 struct init_sec_context_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gssd_ctx_id_t	ctx;
 	gss_OID		actual_mech_type;
 	gss_buffer_desc output_token;
 	uint32_t	ret_flags;
 	uint32_t	time_rec;
 };
 
 struct init_sec_context_args {
 	uint32_t	uid;
 	gssd_cred_id_t	cred;
 	gssd_ctx_id_t	ctx;
 	gssd_name_t	name;
 	gss_OID		mech_type;
 	uint32_t	req_flags;
 	uint32_t	time_req;
 	gss_channel_bindings_t input_chan_bindings;
 	gss_buffer_desc input_token;
 };
 
 struct accept_sec_context_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gssd_ctx_id_t	ctx;
 	gssd_name_t	src_name;
 	gss_OID		mech_type;
 	gss_buffer_desc	output_token;
 	uint32_t	ret_flags;
 	uint32_t	time_rec;
 	gssd_cred_id_t	delegated_cred_handle;
 };
 
 struct accept_sec_context_args {
 	gssd_ctx_id_t	ctx;
 	gssd_cred_id_t	cred;
 	gss_buffer_desc	input_token;
 	gss_channel_bindings_t input_chan_bindings;
 };
 
 struct delete_sec_context_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gss_buffer_desc	output_token;
 };
 
 struct delete_sec_context_args {
 	gssd_ctx_id_t	ctx;
 };
 
 enum sec_context_format {
 	KGSS_HEIMDAL_0_6,
 	KGSS_HEIMDAL_1_1
 };
 
 struct export_sec_context_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	enum sec_context_format format;
 	gss_buffer_desc	interprocess_token;
 };
 
 struct export_sec_context_args {
        gssd_ctx_id_t	ctx;
 };
 
 struct import_name_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gssd_name_t	output_name;
 };
 
 struct import_name_args {
 	gss_buffer_desc	input_name_buffer;
 	gss_OID		input_name_type;
 };
 
 struct canonicalize_name_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gssd_name_t	output_name;
 };
 
 struct canonicalize_name_args {
 	gssd_name_t	input_name;
 	gss_OID		mech_type;
 };
 
 struct export_name_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gss_buffer_desc	exported_name;
 };
 
 struct export_name_args {
 	gssd_name_t	input_name;
 };
 
 struct release_name_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 };
 
 struct release_name_args {
 	gssd_name_t	input_name;
 };
 
 struct pname_to_uid_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	uint32_t	uid;
 	uint32_t	gid;
 	uint32_t	gidlist<>;
 };
 
 struct pname_to_uid_args {
        gssd_name_t	pname;
        gss_OID		mech;
 };
 
 struct acquire_cred_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	gssd_cred_id_t	output_cred;
 	gss_OID_set	actual_mechs;
 	uint32_t	time_rec;
 };
 
 struct acquire_cred_args {
 	uint32_t	uid;
 	gssd_name_t	desired_name;
 	uint32_t	time_req;
 	gss_OID_set	desired_mechs;
 	int		cred_usage;
 };
 
 struct set_cred_option_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 };
 
 struct set_cred_option_args {
        gssd_cred_id_t	cred;
        gss_OID		option_name;
        gss_buffer_desc	option_value;
 };
 
 struct release_cred_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 };
 
 struct release_cred_args {
 	gssd_cred_id_t	cred;
 };
 
 struct display_status_res {
 	uint32_t	major_status;
 	uint32_t	minor_status;
 	uint32_t	message_context;
 	gss_buffer_desc	status_string;
 };
 
 struct display_status_args {
        uint32_t		status_value;
        int		status_type;
        gss_OID		mech_type;
        uint32_t		message_context;
 };
 
+struct ip_to_dns_res {
+	uint32_t	major_status;
+	uint32_t	minor_status;
+	char		dns_name<NI_MAXHOST>;
+};
+
+struct ip_to_dns_args {
+	char		ip_addr<NI_MAXHOST>;
+};
+
 program GSSD {
 	version GSSDVERS {
 		void GSSD_NULL(void) = 0;
 
 		init_sec_context_res
 		GSSD_INIT_SEC_CONTEXT(init_sec_context_args) = 1;
 			
 		accept_sec_context_res
 		GSSD_ACCEPT_SEC_CONTEXT(accept_sec_context_args) = 2;
 			
 		delete_sec_context_res
 		GSSD_DELETE_SEC_CONTEXT(delete_sec_context_args) = 3;
 			
 		export_sec_context_res
 		GSSD_EXPORT_SEC_CONTEXT(export_sec_context_args) = 4;
 			
 		import_name_res
 		GSSD_IMPORT_NAME(import_name_args) = 5;
 
 		canonicalize_name_res
 		GSSD_CANONICALIZE_NAME(canonicalize_name_args) = 6;
 
 		export_name_res
 		GSSD_EXPORT_NAME(export_name_args) = 7;
 
 		release_name_res
 		GSSD_RELEASE_NAME(release_name_args) = 8;
 
 		pname_to_uid_res
 		GSSD_PNAME_TO_UID(pname_to_uid_args) = 9;
 
 		acquire_cred_res
 		GSSD_ACQUIRE_CRED(acquire_cred_args) = 10;
 
 		set_cred_option_res
 		GSSD_SET_CRED_OPTION(set_cred_option_args) = 11;
 
 		release_cred_res
 		GSSD_RELEASE_CRED(release_cred_args) = 12;
 
 		display_status_res
 		GSSD_DISPLAY_STATUS(display_status_args) = 13;
+
+		ip_to_dns_res
+		GSSD_IP_TO_DNS(ip_to_dns_args) = 14;
 	} = 1;
 } = 0x40677373;
diff --git a/sys/modules/kgssapi/Makefile b/sys/modules/kgssapi/Makefile
index 2cf36246137c..a3eb812fd6e6 100644
--- a/sys/modules/kgssapi/Makefile
+++ b/sys/modules/kgssapi/Makefile
@@ -1,55 +1,56 @@
 
 .PATH: ${SRCTOP}/sys/kgssapi ${SRCTOP}/sys/rpc/rpcsec_gss
 KMOD=	kgssapi
 
 SRCS=	gss_accept_sec_context.c \
 	gss_add_oid_set_member.c \
 	gss_acquire_cred.c \
 	gss_canonicalize_name.c \
 	gss_create_empty_oid_set.c \
 	gss_delete_sec_context.c \
 	gss_display_status.c \
 	gss_export_name.c \
 	gss_get_mic.c \
 	gss_init_sec_context.c \
 	gss_impl.c \
 	gss_import_name.c \
+	gss_ip_to_dns.c \
 	gss_names.c \
 	gss_pname_to_uid.c \
 	gss_release_buffer.c \
 	gss_release_cred.c \
 	gss_release_name.c \
 	gss_release_oid_set.c \
 	gss_set_cred_option.c \
 	gss_test_oid_set_member.c \
 	gss_unwrap.c \
 	gss_verify_mic.c \
 	gss_wrap.c \
 	gss_wrap_size_limit.c \
 	gssd_prot.c
 
 SRCS+=	rpcsec_gss.c \
 	rpcsec_gss_conf.c \
 	rpcsec_gss_misc.c \
 	rpcsec_gss_prot.c \
 	svc_rpcsec_gss.c
 
 SRCS+=		kgss_if.h kgss_if.c
 
 SRCS+=		gssd.h gssd_xdr.c gssd_clnt.c
 CLEANFILES=	gssd.h gssd_xdr.c gssd_clnt.c
 
 S=		${SRCTOP}/sys
 
 gssd.h:		$S/kgssapi/gssd.x
 	RPCGEN_CPP=${CPP:Q} rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h
 
 gssd_xdr.c:	$S/kgssapi/gssd.x
 	RPCGEN_CPP=${CPP:Q} rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c
 
 gssd_clnt.c:	$S/kgssapi/gssd.x
 	RPCGEN_CPP=${CPP:Q} rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c
 
 EXPORT_SYMS=	YES
 
 .include <bsd.kmod.mk>
diff --git a/sys/rpc/rpcsec_gss.h b/sys/rpc/rpcsec_gss.h
index 51381762fe29..2475f61a057e 100644
--- a/sys/rpc/rpcsec_gss.h
+++ b/sys/rpc/rpcsec_gss.h
@@ -1,472 +1,489 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright (c) 2008 Doug Rabson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #ifndef _RPCSEC_GSS_H
 #define _RPCSEC_GSS_H
 
 #include <kgssapi/gssapi.h>
 
 #ifndef MAX_GSS_MECH
 #define MAX_GSS_MECH	64
 #endif
 
 /*
  * Define the types of security service required for rpc_gss_seccreate().
  */
 typedef enum {
 	rpc_gss_svc_default	= 0,
 	rpc_gss_svc_none	= 1,
 	rpc_gss_svc_integrity	= 2,
 	rpc_gss_svc_privacy	= 3
 } rpc_gss_service_t;
 
 /*
  * Structure containing options for rpc_gss_seccreate().
  */
 typedef struct {
 	int		req_flags;	/* GSS request bits */
 	int		time_req;	/* requested credential lifetime */
 	gss_cred_id_t	my_cred;	/* GSS credential */
 	gss_channel_bindings_t input_channel_bindings;
 } rpc_gss_options_req_t;
 
 /*
  * Structure containing options returned by rpc_gss_seccreate().
  */
 typedef struct {
 	int		major_status;
 	int		minor_status;
 	u_int		rpcsec_version;
 	int		ret_flags;
 	int		time_req;
 	gss_ctx_id_t	gss_context;
 	char		actual_mechanism[MAX_GSS_MECH];
 } rpc_gss_options_ret_t;
 
 /*
  * Client principal type. Used as an argument to
  * rpc_gss_get_principal_name(). Also referenced by the
  * rpc_gss_rawcred_t structure.
  */
 typedef struct {
 	int		len;
 	char		name[1];
 } *rpc_gss_principal_t;
 
 /*
  * Structure for raw credentials used by rpc_gss_getcred() and
  * rpc_gss_set_callback().
  */
 typedef struct {
 	u_int		version;	/* RPC version number */
 	const char	*mechanism;	/* security mechanism */
 	const char	*qop;		/* quality of protection */
 	rpc_gss_principal_t client_principal; /* client name */
 	const char	*svc_principal;	/* server name */
 	rpc_gss_service_t service;	/* service type */
 } rpc_gss_rawcred_t;
 
 /*
  * Unix credentials derived from raw credentials. Returned by
  * rpc_gss_getcred().
  */
 typedef struct {
 	uid_t		uid;		/* user ID */
 	gid_t		gid;		/* group ID */
 	short		gidlen;
 	gid_t		*gidlist;	/* list of groups */
 } rpc_gss_ucred_t;
 
 /*
  * Structure used to enforce a particular QOP and service.
  */
 typedef struct {
 	bool_t		locked;
 	rpc_gss_rawcred_t *raw_cred;
 } rpc_gss_lock_t;
 
 /*
  * Callback structure used by rpc_gss_set_callback().
  */
 typedef struct {
 	u_int		program;	/* RPC program number */
 	u_int		version;	/* RPC version number */
 					/* user defined callback */
 	bool_t		(*callback)(struct svc_req *req,
 				    gss_cred_id_t deleg,
 				    gss_ctx_id_t gss_context,
 				    rpc_gss_lock_t *lock,
 				    void **cookie);
 } rpc_gss_callback_t;
 
 /*
  * Structure used to return error information by rpc_gss_get_error()
  */
 typedef struct {
 	int		rpc_gss_error;
 	int		system_error;	/* same as errno */
 } rpc_gss_error_t;
 
 /*
  * Values for rpc_gss_error
  */
 #define RPC_GSS_ER_SUCCESS	0	/* no error */
 #define RPC_GSS_ER_SYSTEMERROR	1	/* system error */
 
 __BEGIN_DECLS
 
 #ifdef _KERNEL
 /*
  * Set up a structure of entry points for the kgssapi module and inline
  * functions named rpc_gss_XXX_call() to use them, so that the kgssapi
  * module doesn't need to be loaded for the NFS modules to work using
  * AUTH_SYS. The kgssapi modules will be loaded by the gssd(8) daemon
  * when it is started up and the entry points will then be filled in.
  */
 typedef AUTH	*rpc_gss_secfind_ftype(CLIENT *clnt, struct ucred *cred,
 		    const char *principal, gss_OID mech_oid,
 		    rpc_gss_service_t service);
 typedef void	rpc_gss_secpurge_ftype(CLIENT *clnt);
 typedef AUTH	*rpc_gss_seccreate_ftype(CLIENT *clnt, struct ucred *cred,
 		    const char *clnt_principal, const char *principal,
 		    const char *mechanism, rpc_gss_service_t service,
 		    const char *qop, rpc_gss_options_req_t *options_req,
 		    rpc_gss_options_ret_t *options_ret);
 typedef bool_t	rpc_gss_set_defaults_ftype(AUTH *auth,
 		    rpc_gss_service_t service, const char *qop);
 typedef int	rpc_gss_max_data_length_ftype(AUTH *handle,
 		    int max_tp_unit_len);
 typedef void	rpc_gss_get_error_ftype(rpc_gss_error_t *error);
 typedef bool_t	rpc_gss_mech_to_oid_ftype(const char *mech, gss_OID *oid_ret);
 typedef bool_t	rpc_gss_oid_to_mech_ftype(gss_OID oid, const char **mech_ret);
 typedef bool_t	rpc_gss_qop_to_num_ftype(const char *qop, const char *mech,
 		    u_int *num_ret);
 typedef const char **rpc_gss_get_mechanisms_ftype(void);
 typedef bool_t	rpc_gss_get_versions_ftype(u_int *vers_hi, u_int *vers_lo);
 typedef bool_t	rpc_gss_is_installed_ftype(const char *mech);
 typedef bool_t	rpc_gss_set_svc_name_ftype(const char *principal,
 		    const char *mechanism, u_int req_time, u_int program,
 		    u_int version);
 typedef void	rpc_gss_clear_svc_name_ftype(u_int program, u_int version);
 typedef bool_t	rpc_gss_getcred_ftype(struct svc_req *req,
 		    rpc_gss_rawcred_t **rcred,
 		    rpc_gss_ucred_t **ucred, void **cookie);
 typedef bool_t	rpc_gss_set_callback_ftype(rpc_gss_callback_t *cb);
 typedef void	rpc_gss_clear_callback_ftype(rpc_gss_callback_t *cb);
 typedef bool_t	rpc_gss_get_principal_name_ftype(rpc_gss_principal_t *principal,
 		    const char *mech, const char *name, const char *node,
 		    const char *domain);
 typedef int	rpc_gss_svc_max_data_length_ftype(struct svc_req *req,
 		    int max_tp_unit_len);
 typedef void	rpc_gss_refresh_auth_ftype(AUTH *auth);
+typedef bool_t	rpc_gss_ip_to_srv_principal_ftype(char *ip_addr,
+		    const char *srv_name, char *dns_name);
 
 struct rpc_gss_entries {
 	rpc_gss_secfind_ftype		*rpc_gss_secfind;
 	rpc_gss_secpurge_ftype		*rpc_gss_secpurge;
 	rpc_gss_seccreate_ftype		*rpc_gss_seccreate;
 	rpc_gss_set_defaults_ftype	*rpc_gss_set_defaults;
 	rpc_gss_max_data_length_ftype	*rpc_gss_max_data_length;
 	rpc_gss_get_error_ftype		*rpc_gss_get_error;
 	rpc_gss_mech_to_oid_ftype	*rpc_gss_mech_to_oid;
 	rpc_gss_oid_to_mech_ftype	*rpc_gss_oid_to_mech;
 	rpc_gss_qop_to_num_ftype	*rpc_gss_qop_to_num;
 	rpc_gss_get_mechanisms_ftype	*rpc_gss_get_mechanisms;
 	rpc_gss_get_versions_ftype	*rpc_gss_get_versions;
 	rpc_gss_is_installed_ftype	*rpc_gss_is_installed;
 	rpc_gss_set_svc_name_ftype	*rpc_gss_set_svc_name;
 	rpc_gss_clear_svc_name_ftype	*rpc_gss_clear_svc_name;
 	rpc_gss_getcred_ftype		*rpc_gss_getcred;
 	rpc_gss_set_callback_ftype	*rpc_gss_set_callback;
 	rpc_gss_clear_callback_ftype	*rpc_gss_clear_callback;
 	rpc_gss_get_principal_name_ftype *rpc_gss_get_principal_name;
 	rpc_gss_svc_max_data_length_ftype *rpc_gss_svc_max_data_length;
 	rpc_gss_refresh_auth_ftype	*rpc_gss_refresh_auth;
+	rpc_gss_ip_to_srv_principal_ftype *rpc_gss_ip_to_srv_principal;
 };
 extern struct rpc_gss_entries	rpc_gss_entries;
 
 /* Functions to access the entry points. */
 static __inline AUTH *
 rpc_gss_secfind_call(CLIENT *clnt, struct ucred *cred, const char *principal,
     gss_OID mech_oid, rpc_gss_service_t service)
 {
 	AUTH *ret = NULL;
 
 	if (rpc_gss_entries.rpc_gss_secfind != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_secfind)(clnt, cred, principal,
 		    mech_oid, service);
 	return (ret);
 }
 
 static __inline void
 rpc_gss_secpurge_call(CLIENT *clnt)
 {
 
 	if (rpc_gss_entries.rpc_gss_secpurge != NULL)
 		(*rpc_gss_entries.rpc_gss_secpurge)(clnt);
 }
 
 static __inline AUTH *
 rpc_gss_seccreate_call(CLIENT *clnt, struct ucred *cred,
     const char *clnt_principal, const char *principal, const char *mechanism,
     rpc_gss_service_t service, const char *qop,
     rpc_gss_options_req_t *options_req, rpc_gss_options_ret_t *options_ret)
 {
 	AUTH *ret = NULL;
 
 	if (rpc_gss_entries.rpc_gss_seccreate != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_seccreate)(clnt, cred,
 		    clnt_principal, principal, mechanism, service, qop,
 		    options_req, options_ret);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_set_defaults_call(AUTH *auth, rpc_gss_service_t service,
     const char *qop)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_set_defaults != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_set_defaults)(auth, service,
 		    qop);
 	return (ret);
 }
 
 static __inline int
 rpc_gss_max_data_length_call(AUTH *handle, int max_tp_unit_len)
 {
 	int ret = 0;
 
 	if (rpc_gss_entries.rpc_gss_max_data_length != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_max_data_length)(handle,
 		    max_tp_unit_len);
 	return (ret);
 }
 
 static __inline void
 rpc_gss_get_error_call(rpc_gss_error_t *error)
 {
 
 	if (rpc_gss_entries.rpc_gss_get_error != NULL)
 		(*rpc_gss_entries.rpc_gss_get_error)(error);
 }
 
 static __inline bool_t
 rpc_gss_mech_to_oid_call(const char *mech, gss_OID *oid_ret)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_mech_to_oid != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_mech_to_oid)(mech, oid_ret);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_oid_to_mech_call(gss_OID oid, const char **mech_ret)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_oid_to_mech != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_oid_to_mech)(oid, mech_ret);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_qop_to_num_call(const char *qop, const char *mech, u_int *num_ret)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_qop_to_num != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_qop_to_num)(qop, mech, num_ret);
 	return (ret);
 }
 
 static __inline const char **
 rpc_gss_get_mechanisms_call(void)
 {
 	const char **ret = NULL;
 
 	if (rpc_gss_entries.rpc_gss_get_mechanisms != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_get_mechanisms)();
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_get_versions_call(u_int *vers_hi, u_int *vers_lo)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_get_versions != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_get_versions)(vers_hi, vers_lo);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_is_installed_call(const char *mech)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_is_installed != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_is_installed)(mech);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_set_svc_name_call(const char *principal, const char *mechanism,
     u_int req_time, u_int program, u_int version)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_set_svc_name != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_set_svc_name)(principal,
 		    mechanism, req_time, program, version);
 	return (ret);
 }
 
 static __inline void
 rpc_gss_clear_svc_name_call(u_int program, u_int version)
 {
 
 	if (rpc_gss_entries.rpc_gss_clear_svc_name != NULL)
 		(*rpc_gss_entries.rpc_gss_clear_svc_name)(program, version);
 }
 
 static __inline bool_t
 rpc_gss_getcred_call(struct svc_req *req, rpc_gss_rawcred_t **rcred,
     rpc_gss_ucred_t **ucred, void **cookie)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_getcred != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_getcred)(req, rcred, ucred,
 		    cookie);
 	return (ret);
 }
 
 static __inline bool_t
 rpc_gss_set_callback_call(rpc_gss_callback_t *cb)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_set_callback != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_set_callback)(cb);
 	return (ret);
 }
 
 static __inline void
 rpc_gss_clear_callback_call(rpc_gss_callback_t *cb)
 {
 
 	if (rpc_gss_entries.rpc_gss_clear_callback != NULL)
 		(*rpc_gss_entries.rpc_gss_clear_callback)(cb);
 }
 
 static __inline bool_t
 rpc_gss_get_principal_name_call(rpc_gss_principal_t *principal,
     const char *mech, const char *name, const char *node, const char *domain)
 {
 	bool_t ret = 1;
 
 	if (rpc_gss_entries.rpc_gss_get_principal_name != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_get_principal_name)(principal,
 		    mech, name, node, domain);
 	return (ret);
 }
 
 static __inline int
 rpc_gss_svc_max_data_length_call(struct svc_req *req, int max_tp_unit_len)
 {
 	int ret = 0;
 
 	if (rpc_gss_entries.rpc_gss_svc_max_data_length != NULL)
 		ret = (*rpc_gss_entries.rpc_gss_svc_max_data_length)(req,
 		    max_tp_unit_len);
 	return (ret);
 }
 
 static __inline void
 rpc_gss_refresh_auth_call(AUTH *auth)
 {
 
 	if (rpc_gss_entries.rpc_gss_refresh_auth != NULL)
 		(*rpc_gss_entries.rpc_gss_refresh_auth)(auth);
 }
 
+static __inline bool_t
+rpc_gss_ip_to_srv_principal_call(char *ip_addr, const char *srv_name,
+    char *dns_name)
+{
+	bool_t ret = FALSE;
+
+	if (rpc_gss_entries.rpc_gss_ip_to_srv_principal != NULL)
+		ret = (*rpc_gss_entries.rpc_gss_ip_to_srv_principal)(ip_addr,
+		    srv_name, dns_name);
+	return (ret);
+}
+
 AUTH	*rpc_gss_secfind(CLIENT *clnt, struct ucred *cred,
     const char *principal, gss_OID mech_oid, rpc_gss_service_t service);
 void	rpc_gss_secpurge(CLIENT *clnt);
 void	rpc_gss_refresh_auth(AUTH *auth);
 AUTH	*rpc_gss_seccreate(CLIENT *clnt, struct ucred *cred,
     const char *clnt_principal, const char *principal,
     const char *mechanism, rpc_gss_service_t service,
     const char *qop, rpc_gss_options_req_t *options_req,
     rpc_gss_options_ret_t *options_ret);
 #else	/* !_KERNEL */
 AUTH	*rpc_gss_seccreate(CLIENT *clnt, struct ucred *cred,
     const char *principal, const char *mechanism, rpc_gss_service_t service,
     const char *qop, rpc_gss_options_req_t *options_req,
     rpc_gss_options_ret_t *options_ret);
 #endif	/* _KERNEL */
 bool_t	rpc_gss_set_defaults(AUTH *auth, rpc_gss_service_t service,
     const char *qop);
 int	rpc_gss_max_data_length(AUTH *handle, int max_tp_unit_len);
 void	rpc_gss_get_error(rpc_gss_error_t *error);
 
 bool_t	rpc_gss_mech_to_oid(const char *mech, gss_OID *oid_ret);
 bool_t	rpc_gss_oid_to_mech(gss_OID oid, const char **mech_ret);
 bool_t	rpc_gss_qop_to_num(const char *qop, const char *mech, u_int *num_ret);
 const char **rpc_gss_get_mechanisms(void);
 const char **rpc_gss_get_mech_info(const char *mech, rpc_gss_service_t *service);
 bool_t	rpc_gss_get_versions(u_int *vers_hi, u_int *vers_lo);
 bool_t	rpc_gss_is_installed(const char *mech);
 
 bool_t	rpc_gss_set_svc_name(const char *principal, const char *mechanism,
     u_int req_time, u_int program, u_int version);
 void rpc_gss_clear_svc_name(u_int program, u_int version);
 bool_t	rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred,
     rpc_gss_ucred_t **ucred, void **cookie);
 bool_t	rpc_gss_set_callback(rpc_gss_callback_t *cb);
 void rpc_gss_clear_callback(rpc_gss_callback_t *cb);
 bool_t	rpc_gss_get_principal_name(rpc_gss_principal_t *principal,
     const char *mech, const char *name, const char *node, const char *domain);
 int	rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len);
+bool_t	rpc_gss_ip_to_srv_principal(char *ip_addr, const char *srv_name,
+    char *dns_name);
 
 /*
  * Internal interface from the RPC implementation.
  */
 #ifndef _KERNEL
 bool_t	__rpc_gss_wrap(AUTH *auth, void *header, size_t headerlen,
     XDR* xdrs, xdrproc_t xdr_args, void *args_ptr);
 bool_t	__rpc_gss_unwrap(AUTH *auth, XDR* xdrs, xdrproc_t xdr_args,
     void *args_ptr);
 #endif
 bool_t __rpc_gss_set_error(int rpc_gss_error, int system_error);
 
 __END_DECLS
 
 #endif /* !_RPCSEC_GSS_H */
diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
index 2707c5ed0582..90aa9e0d7d4f 100644
--- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
+++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
@@ -1,1622 +1,1653 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  * Copyright (c) 1990 The Regents of the University of California.
  *
  * Copyright (c) 2008 Doug Rabson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 /*
   svc_rpcsec_gss.c
   
   Copyright (c) 2000 The Regents of the University of Michigan.
   All rights reserved.
 
   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
   All rights reserved, all wrongs reversed.
 
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:
 
   1. Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
   3. Neither the name of the University nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.
 
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
   $Id: svc_auth_gss.c,v 1.27 2002/01/15 15:43:00 andros Exp $
  */
 
 #include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/kobj.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/sx.h>
 #include <sys/ucred.h>
 
 #include <rpc/rpc.h>
 #include <rpc/rpcsec_gss.h>
 
 #include "rpcsec_gss_int.h"
 
 static bool_t   svc_rpc_gss_wrap(SVCAUTH *, struct mbuf **);
 static bool_t   svc_rpc_gss_unwrap(SVCAUTH *, struct mbuf **);
 static void     svc_rpc_gss_release(SVCAUTH *);
 static enum auth_stat svc_rpc_gss(struct svc_req *, struct rpc_msg *);
 static int rpc_gss_svc_getcred(struct svc_req *, struct ucred **, int *);
 
 static const struct svc_auth_ops svc_auth_gss_ops = {
 	.svc_ah_wrap =		svc_rpc_gss_wrap,
 	.svc_ah_unwrap =	svc_rpc_gss_unwrap,
 	.svc_ah_release =	svc_rpc_gss_release,
 };
 
 struct sx svc_rpc_gss_lock;
 
 struct svc_rpc_gss_callback {
 	SLIST_ENTRY(svc_rpc_gss_callback) cb_link;
 	rpc_gss_callback_t	cb_callback;
 };
 SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback);
 KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_callback_list,
     svc_rpc_gss_callbacks) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks);
 
 struct svc_rpc_gss_svc_name {
 	SLIST_ENTRY(svc_rpc_gss_svc_name) sn_link;
 	char			*sn_principal;
 	gss_OID			sn_mech;
 	u_int			sn_req_time;
 	gss_cred_id_t		sn_cred;
 	u_int			sn_program;
 	u_int			sn_version;
 };
 SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name);
 KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_svc_name_list,
     svc_rpc_gss_svc_names) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names);
 
 enum svc_rpc_gss_client_state {
 	CLIENT_NEW,				/* still authenticating */
 	CLIENT_ESTABLISHED,			/* context established */
 	CLIENT_STALE				/* garbage to collect */
 };
 
 #define SVC_RPC_GSS_SEQWINDOW	128
 
 struct svc_rpc_gss_clientid {
 	unsigned long		ci_hostid;
 	uint32_t		ci_boottime;
 	uint32_t		ci_id;
 };
 
 struct svc_rpc_gss_client {
 	TAILQ_ENTRY(svc_rpc_gss_client) cl_link;
 	TAILQ_ENTRY(svc_rpc_gss_client) cl_alllink;
 	volatile u_int		cl_refs;
 	struct sx		cl_lock;
 	struct svc_rpc_gss_clientid cl_id;
 	time_t			cl_expiration;	/* when to gc */
 	enum svc_rpc_gss_client_state cl_state;	/* client state */
 	bool_t			cl_locked;	/* fixed service+qop */
 	gss_ctx_id_t		cl_ctx;		/* context id */
 	gss_cred_id_t		cl_creds;	/* delegated creds */
 	gss_name_t		cl_cname;	/* client name */
 	struct svc_rpc_gss_svc_name *cl_sname;	/* server name used */
 	rpc_gss_rawcred_t	cl_rawcred;	/* raw credentials */
 	rpc_gss_ucred_t		cl_ucred;	/* unix-style credentials */
 	struct ucred		*cl_cred;	/* kernel-style credentials */
 	int			cl_rpcflavor;	/* RPC pseudo sec flavor */
 	bool_t			cl_done_callback; /* TRUE after call */
 	void			*cl_cookie;	/* user cookie from callback */
 	gid_t			cl_gid_storage[NGROUPS];
 	gss_OID			cl_mech;	/* mechanism */
 	gss_qop_t		cl_qop;		/* quality of protection */
 	uint32_t		cl_seqlast;	/* sequence window origin */
 	uint32_t		cl_seqmask[SVC_RPC_GSS_SEQWINDOW/32]; /* bitmask of seqnums */
 };
 TAILQ_HEAD(svc_rpc_gss_client_list, svc_rpc_gss_client);
 
 /*
  * This structure holds enough information to unwrap arguments or wrap
  * results for a given request. We use the rq_clntcred area for this
  * (which is a per-request buffer).
  */
 struct svc_rpc_gss_cookedcred {
 	struct svc_rpc_gss_client *cc_client;
 	rpc_gss_service_t	cc_service;
 	uint32_t		cc_seq;
 };
 
 #define CLIENT_HASH_SIZE	256
 #define CLIENT_MAX		1024
 u_int svc_rpc_gss_client_max = CLIENT_MAX;
 u_int svc_rpc_gss_client_hash_size = CLIENT_HASH_SIZE;
 
 SYSCTL_NODE(_kern, OID_AUTO, rpc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
     "RPC");
 SYSCTL_NODE(_kern_rpc, OID_AUTO, gss, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
     "GSS");
 
 SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_max, CTLFLAG_RW,
     &svc_rpc_gss_client_max, 0,
     "Max number of rpc-gss clients");
 
 SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_hash, CTLFLAG_RDTUN,
     &svc_rpc_gss_client_hash_size, 0,
     "Size of rpc-gss client hash table");
 
 static u_int svc_rpc_gss_lifetime_max = 0;
 SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, lifetime_max, CTLFLAG_RW,
     &svc_rpc_gss_lifetime_max, 0,
     "Maximum lifetime (seconds) of rpc-gss clients");
 
 static u_int svc_rpc_gss_client_count;
 SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_count, CTLFLAG_RD,
     &svc_rpc_gss_client_count, 0,
     "Number of rpc-gss clients");
 
 KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list *, svc_rpc_gss_client_hash);
 KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list, svc_rpc_gss_clients);
 KGSS_VNET_DEFINE_STATIC(uint32_t, svc_rpc_gss_next_clientid) = 1;
 
 static void
 svc_rpc_gss_init(void *unused __unused)
 {
 
 	svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred);
 	sx_init(&svc_rpc_gss_lock, "gsslock");
 }
 SYSINIT(svc_rpc_gss_init, SI_SUB_VFS, SI_ORDER_ANY,
     svc_rpc_gss_init, NULL);
 
 static void
 svc_rpc_gss_cleanup(void *unused __unused)
 {
 
 	sx_destroy(&svc_rpc_gss_lock);
 }
 SYSUNINIT(svc_rpc_gss_cleanup, SI_SUB_VFS, SI_ORDER_ANY,
     svc_rpc_gss_cleanup, NULL);
 
 static void
 svc_rpc_gss_vnetinit(void *unused __unused)
 {
 	int i;
 
 	KGSS_VNET(svc_rpc_gss_client_hash) = mem_alloc(
 	    sizeof(struct svc_rpc_gss_client_list) *
 	    svc_rpc_gss_client_hash_size);
 	for (i = 0; i < svc_rpc_gss_client_hash_size; i++)
 		TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_client_hash)[i]);
 	TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_clients));
 }
 VNET_SYSINIT(svc_rpc_gss_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY,
     svc_rpc_gss_vnetinit, NULL);
 
 static void
 svc_rpc_gss_vnet_cleanup(void *unused __unused)
 {
 
 	mem_free(KGSS_VNET(svc_rpc_gss_client_hash),
 	    sizeof(struct svc_rpc_gss_client_list) *
 	    svc_rpc_gss_client_hash_size);
 }
 VNET_SYSUNINIT(svc_rpc_gss_vnet_cleanup, SI_SUB_VNET_DONE, SI_ORDER_ANY,
     svc_rpc_gss_vnet_cleanup, NULL);
 
 bool_t
 rpc_gss_set_callback(rpc_gss_callback_t *cb)
 {
 	struct svc_rpc_gss_callback *scb;
 
 	scb = mem_alloc(sizeof(struct svc_rpc_gss_callback));
 	if (!scb) {
 		_rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM);
 		return (FALSE);
 	}
 	scb->cb_callback = *cb;
 	sx_xlock(&svc_rpc_gss_lock);
 	SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_callbacks), scb, cb_link);
 	sx_xunlock(&svc_rpc_gss_lock);
 
 	return (TRUE);
 }
 
 void
 rpc_gss_clear_callback(rpc_gss_callback_t *cb)
 {
 	struct svc_rpc_gss_callback *scb;
 
 	sx_xlock(&svc_rpc_gss_lock);
 	SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) {
 		if (scb->cb_callback.program == cb->program
 		    && scb->cb_callback.version == cb->version
 		    && scb->cb_callback.callback == cb->callback) {
 			SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_callbacks), scb,
 			    svc_rpc_gss_callback, cb_link);
 			sx_xunlock(&svc_rpc_gss_lock);
 			mem_free(scb, sizeof(*scb));
 			return;
 		}
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 }
 
 static bool_t
 rpc_gss_acquire_svc_cred(struct svc_rpc_gss_svc_name *sname)
 {
 	OM_uint32		maj_stat, min_stat;
 	gss_buffer_desc		namebuf;
 	gss_name_t		name;
 	gss_OID_set_desc	oid_set;
 
 	oid_set.count = 1;
 	oid_set.elements = sname->sn_mech;
 
 	namebuf.value = (void *) sname->sn_principal;
 	namebuf.length = strlen(sname->sn_principal);
 
 	maj_stat = gss_import_name(&min_stat, &namebuf,
 				   GSS_C_NT_HOSTBASED_SERVICE, &name);
 	if (maj_stat != GSS_S_COMPLETE)
 		return (FALSE);
 
 	if (sname->sn_cred != GSS_C_NO_CREDENTIAL)
 		gss_release_cred(&min_stat, &sname->sn_cred);
 
 	maj_stat = gss_acquire_cred(&min_stat, name,
 	    sname->sn_req_time, &oid_set, GSS_C_ACCEPT, &sname->sn_cred,
 	    NULL, NULL);
 	if (maj_stat != GSS_S_COMPLETE) {
 		gss_release_name(&min_stat, &name);
 		return (FALSE);
 	}
 	gss_release_name(&min_stat, &name);
 
 	return (TRUE);
 }
 
 bool_t
 rpc_gss_set_svc_name(const char *principal, const char *mechanism,
     u_int req_time, u_int program, u_int version)
 {
 	struct svc_rpc_gss_svc_name *sname;
 	gss_OID			mech_oid;
 
 	if (!rpc_gss_mech_to_oid(mechanism, &mech_oid))
 		return (FALSE);
 
 	sname = mem_alloc(sizeof(*sname));
 	if (!sname)
 		return (FALSE);
 	sname->sn_principal = strdup(principal, M_RPC);
 	sname->sn_mech = mech_oid;
 	sname->sn_req_time = req_time;
 	sname->sn_cred = GSS_C_NO_CREDENTIAL;
 	sname->sn_program = program;
 	sname->sn_version = version;
 
 	if (!rpc_gss_acquire_svc_cred(sname)) {
 		free(sname->sn_principal, M_RPC);
 		mem_free(sname, sizeof(*sname));
 		return (FALSE);
 	}
 
 	sx_xlock(&svc_rpc_gss_lock);
 	SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_svc_names), sname, sn_link);
 	sx_xunlock(&svc_rpc_gss_lock);
 
 	return (TRUE);
 }
 
 void
 rpc_gss_clear_svc_name(u_int program, u_int version)
 {
 	OM_uint32		min_stat;
 	struct svc_rpc_gss_svc_name *sname;
 
 	sx_xlock(&svc_rpc_gss_lock);
 	SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), sn_link) {
 		if (sname->sn_program == program
 		    && sname->sn_version == version) {
 			SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_svc_names), sname,
 			    svc_rpc_gss_svc_name, sn_link);
 			sx_xunlock(&svc_rpc_gss_lock);
 			gss_release_cred(&min_stat, &sname->sn_cred);
 			free(sname->sn_principal, M_RPC);
 			mem_free(sname, sizeof(*sname));
 			return;
 		}
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 }
 
 bool_t
 rpc_gss_get_principal_name(rpc_gss_principal_t *principal,
     const char *mech, const char *name, const char *node, const char *domain)
 {
 	OM_uint32		maj_stat, min_stat;
 	gss_OID			mech_oid;
 	size_t			namelen;
 	gss_buffer_desc		buf;
 	gss_name_t		gss_name, gss_mech_name;
 	rpc_gss_principal_t	result;
 
 	if (!rpc_gss_mech_to_oid(mech, &mech_oid))
 		return (FALSE);
 
 	/*
 	 * Construct a gss_buffer containing the full name formatted
 	 * as "name/node@domain" where node and domain are optional.
 	 */
 	namelen = strlen(name) + 1;
 	if (node) {
 		namelen += strlen(node) + 1;
 	}
 	if (domain) {
 		namelen += strlen(domain) + 1;
 	}
 
 	buf.value = mem_alloc(namelen);
 	buf.length = namelen;
 	strcpy((char *) buf.value, name);
 	if (node) {
 		strcat((char *) buf.value, "/");
 		strcat((char *) buf.value, node);
 	}
 	if (domain) {
 		strcat((char *) buf.value, "@");
 		strcat((char *) buf.value, domain);
 	}
 
 	/*
 	 * Convert that to a gss_name_t and then convert that to a
 	 * mechanism name in the selected mechanism.
 	 */
 	maj_stat = gss_import_name(&min_stat, &buf,
 	    GSS_C_NT_USER_NAME, &gss_name);
 	mem_free(buf.value, buf.length);
 	if (maj_stat != GSS_S_COMPLETE) {
 		rpc_gss_log_status("gss_import_name", mech_oid, maj_stat, min_stat);
 		return (FALSE);
 	}
 	maj_stat = gss_canonicalize_name(&min_stat, gss_name, mech_oid,
 	    &gss_mech_name);
 	if (maj_stat != GSS_S_COMPLETE) {
 		rpc_gss_log_status("gss_canonicalize_name", mech_oid, maj_stat,
 		    min_stat);
 		gss_release_name(&min_stat, &gss_name);
 		return (FALSE);
 	}
 	gss_release_name(&min_stat, &gss_name);
 
 	/*
 	 * Export the mechanism name and use that to construct the
 	 * rpc_gss_principal_t result.
 	 */
 	maj_stat = gss_export_name(&min_stat, gss_mech_name, &buf);
 	if (maj_stat != GSS_S_COMPLETE) {
 		rpc_gss_log_status("gss_export_name", mech_oid, maj_stat, min_stat);
 		gss_release_name(&min_stat, &gss_mech_name);
 		return (FALSE);
 	}
 	gss_release_name(&min_stat, &gss_mech_name);
 
 	result = mem_alloc(sizeof(int) + buf.length);
 	if (!result) {
 		gss_release_buffer(&min_stat, &buf);
 		return (FALSE);
 	}
 	result->len = buf.length;
 	memcpy(result->name, buf.value, buf.length);
 	gss_release_buffer(&min_stat, &buf);
 
 	*principal = result;
 	return (TRUE);
 }
 
+/*
+ * Note that the ip_addr and srv_principal pointers can point to the same
+ * buffer, so long as ip_addr is at least strlen(srv_name) + 1 > srv_principal.
+ */
+bool_t
+rpc_gss_ip_to_srv_principal(char *ip_addr, const char *srv_name,
+    char *srv_principal)
+{
+	OM_uint32		maj_stat, min_stat;
+	size_t			len;
+
+	/*
+	 * First fill in the service name and '@'.
+	 */
+	len = strlen(srv_name);
+	if (len > NI_MAXSERV)
+		return (FALSE);
+	memcpy(srv_principal, srv_name, len);
+	srv_principal[len] = '@';
+
+	/*
+	 * Do reverse DNS to get the DNS name for the ip_addr.
+	 */
+	maj_stat = gss_ip_to_dns(&min_stat, ip_addr, &srv_principal[len + 1]);
+	if (maj_stat != GSS_S_COMPLETE) {
+		rpc_gss_log_status("gss_ip_to_dns", NULL, maj_stat, min_stat);
+		return (FALSE);
+	}
+	return (TRUE);
+}
+
 bool_t
 rpc_gss_getcred(struct svc_req *req, rpc_gss_rawcred_t **rcred,
     rpc_gss_ucred_t **ucred, void **cookie)
 {
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 
 	if (req->rq_cred.oa_flavor != RPCSEC_GSS)
 		return (FALSE);
 
 	cc = req->rq_clntcred;
 	client = cc->cc_client;
 	if (rcred)
 		*rcred = &client->cl_rawcred;
 	if (ucred)
 		*ucred = &client->cl_ucred;
 	if (cookie)
 		*cookie = client->cl_cookie;
 	return (TRUE);
 }
 
 /*
  * This simpler interface is used by svc_getcred to copy the cred data
  * into a kernel cred structure.
  */
 static int
 rpc_gss_svc_getcred(struct svc_req *req, struct ucred **crp, int *flavorp)
 {
 	struct ucred *cr;
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 	rpc_gss_ucred_t *uc;
 
 	if (req->rq_cred.oa_flavor != RPCSEC_GSS)
 		return (FALSE);
 
 	cc = req->rq_clntcred;
 	client = cc->cc_client;
 
 	if (flavorp)
 		*flavorp = client->cl_rpcflavor;
 
 	if (client->cl_cred) {
 		*crp = crhold(client->cl_cred);
 		return (TRUE);
 	}
 
 	uc = &client->cl_ucred;
 	cr = client->cl_cred = crget();
 	cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid;
 	cr->cr_rgid = cr->cr_svgid = uc->gid;
 	crsetgroups(cr, uc->gidlen, uc->gidlist);
 	cr->cr_prison = curthread->td_ucred->cr_prison;
 	prison_hold(cr->cr_prison);
 	*crp = crhold(cr);
 
 	return (TRUE);
 }
 
 int
 rpc_gss_svc_max_data_length(struct svc_req *req, int max_tp_unit_len)
 {
 	struct svc_rpc_gss_cookedcred *cc = req->rq_clntcred;
 	struct svc_rpc_gss_client *client = cc->cc_client;
 	int			want_conf;
 	OM_uint32		max;
 	OM_uint32		maj_stat, min_stat;
 	int			result;
 
 	switch (client->cl_rawcred.service) {
 	case rpc_gss_svc_none:
 		return (max_tp_unit_len);
 		break;
 
 	case rpc_gss_svc_default:
 	case rpc_gss_svc_integrity:
 		want_conf = FALSE;
 		break;
 
 	case rpc_gss_svc_privacy:
 		want_conf = TRUE;
 		break;
 
 	default:
 		return (0);
 	}
 
 	maj_stat = gss_wrap_size_limit(&min_stat, client->cl_ctx, want_conf,
 	    client->cl_qop, max_tp_unit_len, &max);
 
 	if (maj_stat == GSS_S_COMPLETE) {
 		result = (int) max;
 		if (result < 0)
 			result = 0;
 		return (result);
 	} else {
 		rpc_gss_log_status("gss_wrap_size_limit", client->cl_mech,
 		    maj_stat, min_stat);
 		return (0);
 	}
 }
 
 static struct svc_rpc_gss_client *
 svc_rpc_gss_find_client(struct svc_rpc_gss_clientid *id)
 {
 	struct svc_rpc_gss_client *client;
 	struct svc_rpc_gss_client_list *list;
 	struct timeval boottime;
 	unsigned long hostid;
 
 	rpc_gss_log_debug("in svc_rpc_gss_find_client(%d)", id->ci_id);
 
 	getcredhostid(curthread->td_ucred, &hostid);
 	getboottime(&boottime);
 	if (id->ci_hostid != hostid || id->ci_boottime != boottime.tv_sec)
 		return (NULL);
 
 	list = &KGSS_VNET(svc_rpc_gss_client_hash)
 	    [id->ci_id % svc_rpc_gss_client_hash_size];
 	sx_xlock(&svc_rpc_gss_lock);
 	TAILQ_FOREACH(client, list, cl_link) {
 		if (client->cl_id.ci_id == id->ci_id) {
 			/*
 			 * Move this client to the front of the LRU
 			 * list.
 			 */
 			TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client,
 			    cl_alllink);
 			TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients),
 			    client, cl_alllink);
 			refcount_acquire(&client->cl_refs);
 			break;
 		}
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 
 	return (client);
 }
 
 static struct svc_rpc_gss_client *
 svc_rpc_gss_create_client(void)
 {
 	struct svc_rpc_gss_client *client;
 	struct svc_rpc_gss_client_list *list;
 	struct timeval boottime;
 	unsigned long hostid;
 
 	rpc_gss_log_debug("in svc_rpc_gss_create_client()");
 
 	client = mem_alloc(sizeof(struct svc_rpc_gss_client));
 	memset(client, 0, sizeof(struct svc_rpc_gss_client));
 
 	/*
 	 * Set the initial value of cl_refs to two.  One for the caller
 	 * and the other to hold onto the client structure until it expires.
 	 */
 	refcount_init(&client->cl_refs, 2);
 	sx_init(&client->cl_lock, "GSS-client");
 	getcredhostid(curthread->td_ucred, &hostid);
 	client->cl_id.ci_hostid = hostid;
 	getboottime(&boottime);
 	client->cl_id.ci_boottime = boottime.tv_sec;
 	client->cl_id.ci_id = KGSS_VNET(svc_rpc_gss_next_clientid)++;
 
 	/*
 	 * Start the client off with a short expiration time. We will
 	 * try to get a saner value from the client creds later.
 	 */
 	client->cl_state = CLIENT_NEW;
 	client->cl_locked = FALSE;
 	client->cl_expiration = time_uptime + 5*60;
 
 	list = &KGSS_VNET(svc_rpc_gss_client_hash)
 	    [client->cl_id.ci_id % svc_rpc_gss_client_hash_size];
 	sx_xlock(&svc_rpc_gss_lock);
 	TAILQ_INSERT_HEAD(list, client, cl_link);
 	TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink);
 	svc_rpc_gss_client_count++;
 	sx_xunlock(&svc_rpc_gss_lock);
 	return (client);
 }
 
 static void
 svc_rpc_gss_destroy_client(struct svc_rpc_gss_client *client)
 {
 	OM_uint32 min_stat;
 
 	rpc_gss_log_debug("in svc_rpc_gss_destroy_client()");
 
 	if (client->cl_ctx)
 		gss_delete_sec_context(&min_stat,
 		    &client->cl_ctx, GSS_C_NO_BUFFER);
 
 	if (client->cl_cname)
 		gss_release_name(&min_stat, &client->cl_cname);
 
 	if (client->cl_rawcred.client_principal)
 		mem_free(client->cl_rawcred.client_principal,
 		    sizeof(*client->cl_rawcred.client_principal)
 		    + client->cl_rawcred.client_principal->len);
 
 	if (client->cl_cred)
 		crfree(client->cl_cred);
 
 	sx_destroy(&client->cl_lock);
 	mem_free(client, sizeof(*client));
 }
 
 /*
  * Drop a reference to a client and free it if that was the last reference.
  */
 static void
 svc_rpc_gss_release_client(struct svc_rpc_gss_client *client)
 {
 
 	if (!refcount_release(&client->cl_refs))
 		return;
 	svc_rpc_gss_destroy_client(client);
 }
 
 /*
  * Remove a client from our global lists.
  * Must be called with svc_rpc_gss_lock held.
  */
 static void
 svc_rpc_gss_forget_client_locked(struct svc_rpc_gss_client *client)
 {
 	struct svc_rpc_gss_client_list *list;
 
 	sx_assert(&svc_rpc_gss_lock, SX_XLOCKED);
 	list = &KGSS_VNET(svc_rpc_gss_client_hash)
 	    [client->cl_id.ci_id % svc_rpc_gss_client_hash_size];
 	TAILQ_REMOVE(list, client, cl_link);
 	TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink);
 	svc_rpc_gss_client_count--;
 }
 
 /*
  * Remove a client from our global lists and free it if we can.
  */
 static void
 svc_rpc_gss_forget_client(struct svc_rpc_gss_client *client)
 {
 	struct svc_rpc_gss_client_list *list;
 	struct svc_rpc_gss_client *tclient;
 
 	list = &KGSS_VNET(svc_rpc_gss_client_hash)
 	    [client->cl_id.ci_id % svc_rpc_gss_client_hash_size];
 	sx_xlock(&svc_rpc_gss_lock);
 	TAILQ_FOREACH(tclient, list, cl_link) {
 		/*
 		 * Make sure this client has not already been removed
 		 * from the lists by svc_rpc_gss_forget_client() or
 		 * svc_rpc_gss_forget_client_locked().
 		 */
 		if (client == tclient) {
 			svc_rpc_gss_forget_client_locked(client);
 			sx_xunlock(&svc_rpc_gss_lock);
 			svc_rpc_gss_release_client(client);
 			return;
 		}
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 }
 
 static void
 svc_rpc_gss_timeout_clients(void)
 {
 	struct svc_rpc_gss_client *client;
 	time_t now = time_uptime;
 
 	rpc_gss_log_debug("in svc_rpc_gss_timeout_clients()");
 
 	/*
 	 * First enforce the max client limit. We keep
 	 * svc_rpc_gss_clients in LRU order.
 	 */
 	sx_xlock(&svc_rpc_gss_lock);
 	client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients),
 	    svc_rpc_gss_client_list);
 	while (svc_rpc_gss_client_count > svc_rpc_gss_client_max && client != NULL) {
 		svc_rpc_gss_forget_client_locked(client);
 		sx_xunlock(&svc_rpc_gss_lock);
 		svc_rpc_gss_release_client(client);
 		sx_xlock(&svc_rpc_gss_lock);
 		client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients),
 		    svc_rpc_gss_client_list);
 	}
 again:
 	TAILQ_FOREACH(client, &KGSS_VNET(svc_rpc_gss_clients), cl_alllink) {
 		if (client->cl_state == CLIENT_STALE
 		    || now > client->cl_expiration) {
 			svc_rpc_gss_forget_client_locked(client);
 			sx_xunlock(&svc_rpc_gss_lock);
 			rpc_gss_log_debug("expiring client %p", client);
 			svc_rpc_gss_release_client(client);
 			sx_xlock(&svc_rpc_gss_lock);
 			goto again;
 		}
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 }
 
 #ifdef DEBUG
 /*
  * OID<->string routines.  These are uuuuugly.
  */
 static OM_uint32
 gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str)
 {
 	char		numstr[128];
 	unsigned long	number;
 	int		numshift;
 	size_t		string_length;
 	size_t		i;
 	unsigned char	*cp;
 	char		*bp;
 
 	/* Decoded according to krb5/gssapi_krb5.c */
 
 	/* First determine the size of the string */
 	string_length = 0;
 	number = 0;
 	numshift = 0;
 	cp = (unsigned char *) oid->elements;
 	number = (unsigned long) cp[0];
 	sprintf(numstr, "%ld ", number/40);
 	string_length += strlen(numstr);
 	sprintf(numstr, "%ld ", number%40);
 	string_length += strlen(numstr);
 	for (i=1; i<oid->length; i++) {
 		if ( (size_t) (numshift+7) < (sizeof(unsigned long)*8)) {
 			number = (number << 7) | (cp[i] & 0x7f);
 			numshift += 7;
 		}
 		else {
 			*minor_status = 0;
 			return(GSS_S_FAILURE);
 		}
 		if ((cp[i] & 0x80) == 0) {
 			sprintf(numstr, "%ld ", number);
 			string_length += strlen(numstr);
 			number = 0;
 			numshift = 0;
 		}
 	}
 	/*
 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
 	 * here for "{ " and "}\0".
 	 */
 	string_length += 4;
 	if ((bp = malloc(string_length, M_GSSAPI, M_WAITOK | M_ZERO))) {
 		strcpy(bp, "{ ");
 		number = (unsigned long) cp[0];
 		sprintf(numstr, "%ld ", number/40);
 		strcat(bp, numstr);
 		sprintf(numstr, "%ld ", number%40);
 		strcat(bp, numstr);
 		number = 0;
 		cp = (unsigned char *) oid->elements;
 		for (i=1; i<oid->length; i++) {
 			number = (number << 7) | (cp[i] & 0x7f);
 			if ((cp[i] & 0x80) == 0) {
 				sprintf(numstr, "%ld ", number);
 				strcat(bp, numstr);
 				number = 0;
 			}
 		}
 		strcat(bp, "}");
 		oid_str->length = strlen(bp)+1;
 		oid_str->value = (void *) bp;
 		*minor_status = 0;
 		return(GSS_S_COMPLETE);
 	}
 	*minor_status = 0;
 	return(GSS_S_FAILURE);
 }
 #endif
 
 static void
 svc_rpc_gss_build_ucred(struct svc_rpc_gss_client *client,
     const gss_name_t name)
 {
 	OM_uint32		maj_stat, min_stat;
 	rpc_gss_ucred_t		*uc = &client->cl_ucred;
 	int			numgroups;
 
 	uc->uid = 65534;
 	uc->gid = 65534;
 	uc->gidlist = client->cl_gid_storage;
 
 	numgroups = NGROUPS;
 	maj_stat = gss_pname_to_unix_cred(&min_stat, name, client->cl_mech,
 	    &uc->uid, &uc->gid, &numgroups, &uc->gidlist[0]);
 	if (GSS_ERROR(maj_stat))
 		uc->gidlen = 0;
 	else
 		uc->gidlen = numgroups;
 }
 
 static void
 svc_rpc_gss_set_flavor(struct svc_rpc_gss_client *client)
 {
 	static gss_OID_desc krb5_mech_oid =
 		{9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
 
 	/*
 	 * Attempt to translate mech type and service into a
 	 * 'pseudo flavor'. Hardwire in krb5 support for now.
 	 */
 	if (kgss_oid_equal(client->cl_mech, &krb5_mech_oid)) {
 		switch (client->cl_rawcred.service) {
 		case rpc_gss_svc_default:
 		case rpc_gss_svc_none:
 			client->cl_rpcflavor = RPCSEC_GSS_KRB5;
 			break;
 		case rpc_gss_svc_integrity:
 			client->cl_rpcflavor = RPCSEC_GSS_KRB5I;
 			break;
 		case rpc_gss_svc_privacy:
 			client->cl_rpcflavor = RPCSEC_GSS_KRB5P;
 			break;
 		}
 	} else {
 		client->cl_rpcflavor = RPCSEC_GSS;
 	}
 }
 
 static bool_t
 svc_rpc_gss_accept_sec_context(struct svc_rpc_gss_client *client,
 			       struct svc_req *rqst,
 			       struct rpc_gss_init_res *gr,
 			       struct rpc_gss_cred *gc)
 {
 	gss_buffer_desc		recv_tok;
 	gss_OID			mech;
 	OM_uint32		maj_stat = 0, min_stat = 0, ret_flags;
 	OM_uint32		cred_lifetime;
 	struct svc_rpc_gss_svc_name *sname;
 
 	rpc_gss_log_debug("in svc_rpc_gss_accept_context()");
 	
 	/* Deserialize arguments. */
 	memset(&recv_tok, 0, sizeof(recv_tok));
 	
 	if (!svc_getargs(rqst,
 		(xdrproc_t) xdr_gss_buffer_desc,
 		(caddr_t) &recv_tok)) {
 		client->cl_state = CLIENT_STALE;
 		return (FALSE);
 	}
 
 	/*
 	 * First time round, try all the server names we have until
 	 * one matches. Afterwards, stick with that one.
 	 */
 	sx_xlock(&svc_rpc_gss_lock);
 	if (!client->cl_sname) {
 		SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names),
 		    sn_link) {
 			if (sname->sn_program == rqst->rq_prog
 			    && sname->sn_version == rqst->rq_vers) {
 			retry:
 				gr->gr_major = gss_accept_sec_context(
 					&gr->gr_minor,
 					&client->cl_ctx,
 					sname->sn_cred,
 					&recv_tok,
 					GSS_C_NO_CHANNEL_BINDINGS,
 					&client->cl_cname,
 					&mech,
 					&gr->gr_token,
 					&ret_flags,
 					&cred_lifetime,
 					&client->cl_creds);
 				if (gr->gr_major == 
 				    GSS_S_CREDENTIALS_EXPIRED) {
 					/*
 					 * Either our creds really did
 					 * expire or gssd was
 					 * restarted.
 					 */
 					if (rpc_gss_acquire_svc_cred(sname))
 						goto retry;
 				}
 				client->cl_sname = sname;
 				break;
 			}
 		}
 		if (!sname) {
 			xdr_free((xdrproc_t) xdr_gss_buffer_desc,
 			    (char *) &recv_tok);
 			sx_xunlock(&svc_rpc_gss_lock);
 			return (FALSE);
 		}
 	} else {
 		gr->gr_major = gss_accept_sec_context(
 			&gr->gr_minor,
 			&client->cl_ctx,
 			client->cl_sname->sn_cred,
 			&recv_tok,
 			GSS_C_NO_CHANNEL_BINDINGS,
 			&client->cl_cname,
 			&mech,
 			&gr->gr_token,
 			&ret_flags,
 			&cred_lifetime,
 			NULL);
 	}
 	sx_xunlock(&svc_rpc_gss_lock);
 	
 	xdr_free((xdrproc_t) xdr_gss_buffer_desc, (char *) &recv_tok);
 
 	/*
 	 * If we get an error from gss_accept_sec_context, send the
 	 * reply anyway so that the client gets a chance to see what
 	 * is wrong.
 	 */
 	if (gr->gr_major != GSS_S_COMPLETE &&
 	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
 		rpc_gss_log_status("accept_sec_context", client->cl_mech,
 		    gr->gr_major, gr->gr_minor);
 		client->cl_state = CLIENT_STALE;
 		return (TRUE);
 	}
 
 	gr->gr_handle.value = &client->cl_id;
 	gr->gr_handle.length = sizeof(client->cl_id);
 	gr->gr_win = SVC_RPC_GSS_SEQWINDOW;
 	
 	/* Save client info. */
 	client->cl_mech = mech;
 	client->cl_qop = GSS_C_QOP_DEFAULT;
 	client->cl_done_callback = FALSE;
 
 	if (gr->gr_major == GSS_S_COMPLETE) {
 		gss_buffer_desc	export_name;
 
 		/*
 		 * Change client expiration time to be near when the
 		 * client creds expire (or 24 hours if we can't figure
 		 * that out).
 		 */
 		if (cred_lifetime == GSS_C_INDEFINITE)
 			cred_lifetime = 24*60*60;
 
 		/*
 		 * Cap cred_lifetime if sysctl kern.rpc.gss.lifetime_max is set.
 		 */
 		if (svc_rpc_gss_lifetime_max > 0 && cred_lifetime >
 		    svc_rpc_gss_lifetime_max)
 			cred_lifetime = svc_rpc_gss_lifetime_max;
 		
 		client->cl_expiration = time_uptime + cred_lifetime;
 
 		/*
 		 * Fill in cred details in the rawcred structure.
 		 */
 		client->cl_rawcred.version = RPCSEC_GSS_VERSION;
 		rpc_gss_oid_to_mech(mech, &client->cl_rawcred.mechanism);
 		maj_stat = gss_export_name(&min_stat, client->cl_cname,
 		    &export_name);
 		if (maj_stat != GSS_S_COMPLETE) {
 			rpc_gss_log_status("gss_export_name", client->cl_mech,
 			    maj_stat, min_stat);
 			return (FALSE);
 		}
 		client->cl_rawcred.client_principal =
 			mem_alloc(sizeof(*client->cl_rawcred.client_principal)
 			    + export_name.length);
 		client->cl_rawcred.client_principal->len = export_name.length;
 		memcpy(client->cl_rawcred.client_principal->name,
 		    export_name.value, export_name.length);
 		gss_release_buffer(&min_stat, &export_name);
 		client->cl_rawcred.svc_principal =
 			client->cl_sname->sn_principal;
 		client->cl_rawcred.service = gc->gc_svc;
 
 		/*
 		 * Use gss_pname_to_uid to map to unix creds. For
 		 * kerberos5, this uses krb5_aname_to_localname.
 		 */
 		svc_rpc_gss_build_ucred(client, client->cl_cname);
 		svc_rpc_gss_set_flavor(client);
 		gss_release_name(&min_stat, &client->cl_cname);
 
 #ifdef DEBUG
 		{
 			gss_buffer_desc mechname;
 
 			gss_oid_to_str(&min_stat, mech, &mechname);
 			
 			rpc_gss_log_debug("accepted context for %s with "
 			    "<mech %.*s, qop %d, svc %d>",
 			    client->cl_rawcred.client_principal->name,
 			    mechname.length, (char *)mechname.value,
 			    client->cl_qop, client->cl_rawcred.service);
 
 			gss_release_buffer(&min_stat, &mechname);
 		}
 #endif /* DEBUG */
 	}
 	return (TRUE);
 }
 
 static bool_t
 svc_rpc_gss_validate(struct svc_rpc_gss_client *client, struct rpc_msg *msg,
     gss_qop_t *qop, rpc_gss_proc_t gcproc)
 {
 	struct opaque_auth	*oa;
 	gss_buffer_desc		 rpcbuf, checksum;
 	OM_uint32		 maj_stat, min_stat;
 	gss_qop_t		 qop_state;
 	int32_t			 rpchdr[128 / sizeof(int32_t)];
 	int32_t			*buf;
 
 	rpc_gss_log_debug("in svc_rpc_gss_validate()");
 	
 	memset(rpchdr, 0, sizeof(rpchdr));
 
 	/* Reconstruct RPC header for signing (from xdr_callmsg). */
 	buf = rpchdr;
 	IXDR_PUT_LONG(buf, msg->rm_xid);
 	IXDR_PUT_ENUM(buf, msg->rm_direction);
 	IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers);
 	IXDR_PUT_LONG(buf, msg->rm_call.cb_prog);
 	IXDR_PUT_LONG(buf, msg->rm_call.cb_vers);
 	IXDR_PUT_LONG(buf, msg->rm_call.cb_proc);
 	oa = &msg->rm_call.cb_cred;
 	IXDR_PUT_ENUM(buf, oa->oa_flavor);
 	IXDR_PUT_LONG(buf, oa->oa_length);
 	if (oa->oa_length) {
 		memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
 		buf += RNDUP(oa->oa_length) / sizeof(int32_t);
 	}
 	rpcbuf.value = rpchdr;
 	rpcbuf.length = (u_char *)buf - (u_char *)rpchdr;
 
 	checksum.value = msg->rm_call.cb_verf.oa_base;
 	checksum.length = msg->rm_call.cb_verf.oa_length;
 	
 	maj_stat = gss_verify_mic(&min_stat, client->cl_ctx, &rpcbuf, &checksum,
 				  &qop_state);
 	
 	if (maj_stat != GSS_S_COMPLETE) {
 		rpc_gss_log_status("gss_verify_mic", client->cl_mech,
 		    maj_stat, min_stat);
 		/*
 		 * A bug in some versions of the Linux client generates a
 		 * Destroy operation with a bogus encrypted checksum. Deleting
 		 * the credential handle for that case causes the mount to fail.
 		 * Since the checksum is bogus (gss_verify_mic() failed), it
 		 * doesn't make sense to destroy the handle and not doing so
 		 * fixes the Linux mount.
 		 */
 		if (gcproc != RPCSEC_GSS_DESTROY)
 			client->cl_state = CLIENT_STALE;
 		return (FALSE);
 	}
 
 	*qop = qop_state;
 	return (TRUE);
 }
 
 static bool_t
 svc_rpc_gss_nextverf(struct svc_rpc_gss_client *client,
     struct svc_req *rqst, u_int seq)
 {
 	gss_buffer_desc		signbuf;
 	gss_buffer_desc		mic;
 	OM_uint32		maj_stat, min_stat;
 	uint32_t		nseq;       
 
 	rpc_gss_log_debug("in svc_rpc_gss_nextverf()");
 
 	nseq = htonl(seq);
 	signbuf.value = &nseq;
 	signbuf.length = sizeof(nseq);
 
 	maj_stat = gss_get_mic(&min_stat, client->cl_ctx, client->cl_qop,
 	    &signbuf, &mic);
 
 	if (maj_stat != GSS_S_COMPLETE) {
 		rpc_gss_log_status("gss_get_mic", client->cl_mech, maj_stat, min_stat);
 		client->cl_state = CLIENT_STALE;
 		return (FALSE);
 	}
 
 	KASSERT(mic.length <= MAX_AUTH_BYTES,
 	    ("MIC too large for RPCSEC_GSS"));
 
 	rqst->rq_verf.oa_flavor = RPCSEC_GSS;
 	rqst->rq_verf.oa_length = mic.length;
 	bcopy(mic.value, rqst->rq_verf.oa_base, mic.length);
 
 	gss_release_buffer(&min_stat, &mic);
 	
 	return (TRUE);
 }
 
 static bool_t
 svc_rpc_gss_callback(struct svc_rpc_gss_client *client, struct svc_req *rqst)
 {
 	struct svc_rpc_gss_callback *scb;
 	rpc_gss_lock_t	lock;
 	void		*cookie;
 	bool_t		cb_res;
 	bool_t		result;
 
 	/*
 	 * See if we have a callback for this guy.
 	 */
 	result = TRUE;
 	SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) {
 		if (scb->cb_callback.program == rqst->rq_prog
 		    && scb->cb_callback.version == rqst->rq_vers) {
 			/*
 			 * This one matches. Call the callback and see
 			 * if it wants to veto or something.
 			 */
 			lock.locked = FALSE;
 			lock.raw_cred = &client->cl_rawcred;
 			cb_res = scb->cb_callback.callback(rqst,
 			    client->cl_creds,
 			    client->cl_ctx,
 			    &lock,
 			    &cookie);
 
 			if (!cb_res) {
 				client->cl_state = CLIENT_STALE;
 				result = FALSE;
 				break;
 			}
 
 			/*
 			 * The callback accepted the connection - it
 			 * is responsible for freeing client->cl_creds
 			 * now.
 			 */
 			client->cl_creds = GSS_C_NO_CREDENTIAL;
 			client->cl_locked = lock.locked;
 			client->cl_cookie = cookie;
 			return (TRUE);
 		}
 	}
 
 	/*
 	 * Either no callback exists for this program/version or one
 	 * of the callbacks rejected the connection. We just need to
 	 * clean up the delegated client creds, if any.
 	 */
 	if (client->cl_creds) {
 		OM_uint32 min_ver;
 		gss_release_cred(&min_ver, &client->cl_creds);
 	}
 	return (result);
 }
 
 static bool_t
 svc_rpc_gss_check_replay(struct svc_rpc_gss_client *client, uint32_t seq)
 {
 	uint32_t offset;
 	int word, bit;
 	bool_t result;
 
 	sx_xlock(&client->cl_lock);
 	if (seq <= client->cl_seqlast) {
 		/*
 		 * The request sequence number is less than
 		 * the largest we have seen so far. If it is
 		 * outside the window or if we have seen a
 		 * request with this sequence before, silently
 		 * discard it.
 		 */
 		offset = client->cl_seqlast - seq;
 		if (offset >= SVC_RPC_GSS_SEQWINDOW) {
 			result = FALSE;
 			goto out;
 		}
 		word = offset / 32;
 		bit = offset % 32;
 		if (client->cl_seqmask[word] & (1 << bit)) {
 			result = FALSE;
 			goto out;
 		}
 	}
 
 	result = TRUE;
 out:
 	sx_xunlock(&client->cl_lock);
 	return (result);
 }
 
 static void
 svc_rpc_gss_update_seq(struct svc_rpc_gss_client *client, uint32_t seq)
 {
 	int offset, i, word, bit;
 	uint32_t carry, newcarry;
 
 	sx_xlock(&client->cl_lock);
 	if (seq > client->cl_seqlast) {
 		/*
 		 * This request has a sequence number greater
 		 * than any we have seen so far. Advance the
 		 * seq window and set bit zero of the window
 		 * (which corresponds to the new sequence
 		 * number)
 		 */
 		offset = seq - client->cl_seqlast;
 		while (offset > 32) {
 			for (i = (SVC_RPC_GSS_SEQWINDOW / 32) - 1;
 			     i > 0; i--) {
 				client->cl_seqmask[i] = client->cl_seqmask[i-1];
 			}
 			client->cl_seqmask[0] = 0;
 			offset -= 32;
 		}
 		carry = 0;
 		for (i = 0; i < SVC_RPC_GSS_SEQWINDOW / 32; i++) {
 			newcarry = client->cl_seqmask[i] >> (32 - offset);
 			client->cl_seqmask[i] =
 				(client->cl_seqmask[i] << offset) | carry;
 			carry = newcarry;
 		}
 		client->cl_seqmask[0] |= 1;
 		client->cl_seqlast = seq;
 	} else {
 		offset = client->cl_seqlast - seq;
 		word = offset / 32;
 		bit = offset % 32;
 		client->cl_seqmask[word] |= (1 << bit);
 	}
 	sx_xunlock(&client->cl_lock);
 }
 
 enum auth_stat
 svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg)
 
 {
 	OM_uint32		 min_stat;
 	XDR	 		 xdrs;
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 	struct rpc_gss_cred	 gc;
 	struct rpc_gss_init_res	 gr;
 	gss_qop_t		 qop;
 	int			 call_stat;
 	enum auth_stat		 result;
 	
 	KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread));
 	rpc_gss_log_debug("in svc_rpc_gss()");
 	
 	/* Garbage collect old clients. */
 	svc_rpc_gss_timeout_clients();
 
 	/* Initialize reply. */
 	rqst->rq_verf = _null_auth;
 
 	/* Deserialize client credentials. */
 	if (rqst->rq_cred.oa_length <= 0) {
 		KGSS_CURVNET_RESTORE();
 		return (AUTH_BADCRED);
 	}
 	
 	memset(&gc, 0, sizeof(gc));
 	
 	xdrmem_create(&xdrs, rqst->rq_cred.oa_base,
 	    rqst->rq_cred.oa_length, XDR_DECODE);
 	
 	if (!xdr_rpc_gss_cred(&xdrs, &gc)) {
 		XDR_DESTROY(&xdrs);
 		KGSS_CURVNET_RESTORE();
 		return (AUTH_BADCRED);
 	}
 	XDR_DESTROY(&xdrs);
 
 	client = NULL;
 
 	/* Check version. */
 	if (gc.gc_version != RPCSEC_GSS_VERSION) {
 		result = AUTH_BADCRED;
 		goto out;
 	}
 
 	/* Check the proc and find the client (or create it) */
 	if (gc.gc_proc == RPCSEC_GSS_INIT) {
 		if (gc.gc_handle.length != 0) {
 			result = AUTH_BADCRED;
 			goto out;
 		}
 		client = svc_rpc_gss_create_client();
 	} else {
 		struct svc_rpc_gss_clientid *p;
 		if (gc.gc_handle.length != sizeof(*p)) {
 			result = AUTH_BADCRED;
 			goto out;
 		}
 		p = gc.gc_handle.value;
 		client = svc_rpc_gss_find_client(p);
 		if (!client) {
 			/*
 			 * Can't find the client - we may have
 			 * destroyed it - tell the other side to
 			 * re-authenticate.
 			 */
 			result = RPCSEC_GSS_CREDPROBLEM;
 			goto out;
 		}
 	}
 	cc = rqst->rq_clntcred;
 	cc->cc_client = client;
 	cc->cc_service = gc.gc_svc;
 	cc->cc_seq = gc.gc_seq;
 
 	/*
 	 * The service and sequence number must be ignored for
 	 * RPCSEC_GSS_INIT and RPCSEC_GSS_CONTINUE_INIT.
 	 */
 	if (gc.gc_proc != RPCSEC_GSS_INIT
 	    && gc.gc_proc != RPCSEC_GSS_CONTINUE_INIT) {
 		/*
 		 * Check for sequence number overflow.
 		 */
 		if (gc.gc_seq >= MAXSEQ) {
 			result = RPCSEC_GSS_CTXPROBLEM;
 			goto out;
 		}
 
 		/*
 		 * Check for valid service.
 		 */
 		if (gc.gc_svc != rpc_gss_svc_none &&
 		    gc.gc_svc != rpc_gss_svc_integrity &&
 		    gc.gc_svc != rpc_gss_svc_privacy) {
 			result = AUTH_BADCRED;
 			goto out;
 		}
 	}
 
 	/* Handle RPCSEC_GSS control procedure. */
 	switch (gc.gc_proc) {
 
 	case RPCSEC_GSS_INIT:
 	case RPCSEC_GSS_CONTINUE_INIT:
 		if (rqst->rq_proc != NULLPROC) {
 			result = AUTH_REJECTEDCRED;
 			break;
 		}
 
 		memset(&gr, 0, sizeof(gr));
 		if (!svc_rpc_gss_accept_sec_context(client, rqst, &gr, &gc)) {
 			result = AUTH_REJECTEDCRED;
 			break;
 		}
 
 		if (gr.gr_major == GSS_S_COMPLETE) {
 			/*
 			 * We borrow the space for the call verf to
 			 * pack our reply verf.
 			 */
 			rqst->rq_verf = msg->rm_call.cb_verf;
 			if (!svc_rpc_gss_nextverf(client, rqst, gr.gr_win)) {
 				result = AUTH_REJECTEDCRED;
 				break;
 			}
 		} else {
 			rqst->rq_verf = _null_auth;
 		}
 		
 		call_stat = svc_sendreply(rqst,
 		    (xdrproc_t) xdr_rpc_gss_init_res,
 		    (caddr_t) &gr);
 
 		gss_release_buffer(&min_stat, &gr.gr_token);
 
 		if (!call_stat) {
 			result = AUTH_FAILED;
 			break;
 		}
 
 		if (gr.gr_major == GSS_S_COMPLETE)
 			client->cl_state = CLIENT_ESTABLISHED;
 
 		result = RPCSEC_GSS_NODISPATCH;
 		break;
 		
 	case RPCSEC_GSS_DATA:
 	case RPCSEC_GSS_DESTROY:
 		if (!svc_rpc_gss_check_replay(client, gc.gc_seq)) {
 			result = RPCSEC_GSS_NODISPATCH;
 			break;
 		}
 
 		if (!svc_rpc_gss_validate(client, msg, &qop, gc.gc_proc)) {
 			result = RPCSEC_GSS_CREDPROBLEM;
 			break;
 		}
 		
 		/*
 		 * We borrow the space for the call verf to pack our
 		 * reply verf.
 		 */
 		rqst->rq_verf = msg->rm_call.cb_verf;
 		if (!svc_rpc_gss_nextverf(client, rqst, gc.gc_seq)) {
 			result = RPCSEC_GSS_CTXPROBLEM;
 			break;
 		}
 
 		svc_rpc_gss_update_seq(client, gc.gc_seq);
 
 		/*
 		 * Change the SVCAUTH ops on the request to point at
 		 * our own code so that we can unwrap the arguments
 		 * and wrap the result. The caller will re-set this on
 		 * every request to point to a set of null wrap/unwrap
 		 * methods. Acquire an extra reference to the client
 		 * which will be released by svc_rpc_gss_release()
 		 * after the request has finished processing.
 		 */
 		refcount_acquire(&client->cl_refs);
 		rqst->rq_auth.svc_ah_ops = &svc_auth_gss_ops;
 		rqst->rq_auth.svc_ah_private = cc;
 
 		if (gc.gc_proc == RPCSEC_GSS_DATA) {
 			/*
 			 * We might be ready to do a callback to the server to
 			 * see if it wants to accept/reject the connection.
 			 */
 			sx_xlock(&client->cl_lock);
 			if (!client->cl_done_callback) {
 				client->cl_done_callback = TRUE;
 				client->cl_qop = qop;
 				client->cl_rawcred.qop = _rpc_gss_num_to_qop(
 					client->cl_rawcred.mechanism, qop);
 				if (!svc_rpc_gss_callback(client, rqst)) {
 					result = AUTH_REJECTEDCRED;
 					sx_xunlock(&client->cl_lock);
 					break;
 				}
 			}
 			sx_xunlock(&client->cl_lock);
 
 			/*
 			 * If the server has locked this client to a
 			 * particular service+qop pair, enforce that
 			 * restriction now.
 			 */
 			if (client->cl_locked) {
 				if (client->cl_rawcred.service != gc.gc_svc) {
 					result = AUTH_FAILED;
 					break;
 				} else if (client->cl_qop != qop) {
 					result = AUTH_BADVERF;
 					break;
 				}
 			}
 
 			/*
 			 * If the qop changed, look up the new qop
 			 * name for rawcred.
 			 */
 			if (client->cl_qop != qop) {
 				client->cl_qop = qop;
 				client->cl_rawcred.qop = _rpc_gss_num_to_qop(
 					client->cl_rawcred.mechanism, qop);
 			}
 
 			/*
 			 * Make sure we use the right service value
 			 * for unwrap/wrap.
 			 */
 			if (client->cl_rawcred.service != gc.gc_svc) {
 				client->cl_rawcred.service = gc.gc_svc;
 				svc_rpc_gss_set_flavor(client);
 			}
 
 			result = AUTH_OK;
 		} else {
 			if (rqst->rq_proc != NULLPROC) {
 				result = AUTH_REJECTEDCRED;
 				break;
 			}
 
 			call_stat = svc_sendreply(rqst,
 			    (xdrproc_t) xdr_void, (caddr_t) NULL);
 
 			if (!call_stat) {
 				result = AUTH_FAILED;
 				break;
 			}
 
 			svc_rpc_gss_forget_client(client);
 
 			result = RPCSEC_GSS_NODISPATCH;
 			break;
 		}
 		break;
 
 	default:
 		result = AUTH_BADCRED;
 		break;
 	}
 out:
 	if (client)
 		svc_rpc_gss_release_client(client);
 
 	xdr_free((xdrproc_t) xdr_rpc_gss_cred, (char *) &gc);
 	KGSS_CURVNET_RESTORE();
 	return (result);
 }
 
 static bool_t
 svc_rpc_gss_wrap(SVCAUTH *auth, struct mbuf **mp)
 {
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 	
 	rpc_gss_log_debug("in svc_rpc_gss_wrap()");
 
 	cc = (struct svc_rpc_gss_cookedcred *) auth->svc_ah_private;
 	client = cc->cc_client;
 	if (client->cl_state != CLIENT_ESTABLISHED
 	    || cc->cc_service == rpc_gss_svc_none || *mp == NULL) {
 		return (TRUE);
 	}
 	
 	return (xdr_rpc_gss_wrap_data(mp,
 		client->cl_ctx, client->cl_qop,
 		cc->cc_service, cc->cc_seq));
 }
 
 static bool_t
 svc_rpc_gss_unwrap(SVCAUTH *auth, struct mbuf **mp)
 {
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 
 	rpc_gss_log_debug("in svc_rpc_gss_unwrap()");
 	
 	cc = (struct svc_rpc_gss_cookedcred *) auth->svc_ah_private;
 	client = cc->cc_client;
 	if (client->cl_state != CLIENT_ESTABLISHED
 	    || cc->cc_service == rpc_gss_svc_none) {
 		return (TRUE);
 	}
 
 	return (xdr_rpc_gss_unwrap_data(mp,
 		client->cl_ctx, client->cl_qop,
 		cc->cc_service, cc->cc_seq));
 }
 
 static void
 svc_rpc_gss_release(SVCAUTH *auth)
 {
 	struct svc_rpc_gss_cookedcred *cc;
 	struct svc_rpc_gss_client *client;
 
 	rpc_gss_log_debug("in svc_rpc_gss_release()");
 
 	cc = (struct svc_rpc_gss_cookedcred *) auth->svc_ah_private;
 	client = cc->cc_client;
 	svc_rpc_gss_release_client(client);
 }