summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-12-27 14:58:52 +0000
committerdim <dim@FreeBSD.org>2014-12-27 14:58:52 +0000
commit1848cf1db38654a8dfebddc939ea4560806c375f (patch)
treeb5ae6abea47431ce3367e56359a6bc862d797a70 /sys
parentf0e9784165ce886f2c35a96523b61260ec3bc3cf (diff)
parent488bc65a703bf123118544b08e8bb56682e35280 (diff)
downloadFreeBSD-src-1848cf1db38654a8dfebddc939ea4560806c375f.zip
FreeBSD-src-1848cf1db38654a8dfebddc939ea4560806c375f.tar.gz
Merge ^/head r274961 through r276301.
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/trap.c3
-rw-r--r--sys/amd64/conf/NOTES2
-rw-r--r--sys/amd64/include/vmm.h2
-rw-r--r--sys/amd64/vmm/amd/svm.c96
-rw-r--r--sys/amd64/vmm/intel/vmcs.c6
-rw-r--r--sys/amd64/vmm/intel/vmcs.h2
-rw-r--r--sys/amd64/vmm/intel/vmx.c76
-rw-r--r--sys/amd64/vmm/intel/vmx_msr.c26
-rw-r--r--sys/amd64/vmm/io/vatpic.c41
-rw-r--r--sys/amd64/vmm/vmm.c12
-rw-r--r--sys/arm/allwinner/a20/std.a201
-rw-r--r--sys/arm/allwinner/std.a101
-rw-r--r--sys/arm/altera/socfpga/std.socfpga1
-rw-r--r--sys/arm/arm/db_trace.c19
-rw-r--r--sys/arm/arm/dump_machdep.c16
-rw-r--r--sys/arm/arm/exception.S50
-rw-r--r--sys/arm/arm/gdb_machdep.c24
-rw-r--r--sys/arm/arm/genassym.c19
-rw-r--r--sys/arm/arm/gic.c149
-rw-r--r--sys/arm/arm/identcpu.c2
-rw-r--r--sys/arm/arm/intr.c39
-rw-r--r--sys/arm/arm/machdep.c22
-rw-r--r--sys/arm/arm/mp_machdep.c4
-rw-r--r--sys/arm/arm/nexus.c28
-rw-r--r--sys/arm/arm/stack_machdep.c2
-rw-r--r--sys/arm/arm/swtch.S128
-rw-r--r--sys/arm/arm/trap.c9
-rw-r--r--sys/arm/arm/vm_machdep.c88
-rw-r--r--sys/arm/at91/at91_machdep.c2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c1818
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_intr.c29
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_mbox.c36
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_mbox.h3
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h273
-rw-r--r--sys/arm/broadcom/bcm2835/files.bcm28352
-rw-r--r--sys/arm/broadcom/bcm2835/std.bcm28351
-rw-r--r--sys/arm/conf/APALIS-IMX66
-rw-r--r--sys/arm/conf/ARMADAXP94
-rw-r--r--sys/arm/conf/BEAGLEBONE54
-rw-r--r--sys/arm/conf/CHROMEBOOK-PEACH-PIT18
-rw-r--r--sys/arm/conf/CNS11XXNAS6
-rw-r--r--sys/arm/conf/CUBIEBOARD55
-rw-r--r--sys/arm/conf/CUBIEBOARD285
-rw-r--r--sys/arm/conf/DIGI-CCWMX536
-rw-r--r--sys/arm/conf/DOCKSTAR94
-rw-r--r--sys/arm/conf/DREAMPLUG-100198
-rw-r--r--sys/arm/conf/EA32502
-rw-r--r--sys/arm/conf/EFIKA_MX67
-rw-r--r--sys/arm/conf/EXYNOS5.common71
-rw-r--r--sys/arm/conf/HL2012
-rw-r--r--sys/arm/conf/IMX5352
-rw-r--r--sys/arm/conf/IMX53-QSB4
-rw-r--r--sys/arm/conf/IMX6216
-rw-r--r--sys/arm/conf/PANDABOARD50
-rw-r--r--sys/arm/conf/RK318869
-rw-r--r--sys/arm/conf/RPI-B85
-rw-r--r--sys/arm/conf/SAM9260EK2
-rw-r--r--sys/arm/conf/SOCKIT59
-rw-r--r--sys/arm/conf/SOCKIT-BERI59
-rw-r--r--sys/arm/conf/VERSATILEPB66
-rw-r--r--sys/arm/conf/VYBRID96
-rw-r--r--sys/arm/conf/WANDBOARD-DUAL4
-rw-r--r--sys/arm/conf/WANDBOARD-QUAD4
-rw-r--r--sys/arm/conf/WANDBOARD-SOLO4
-rw-r--r--sys/arm/conf/ZEDBOARD87
-rw-r--r--sys/arm/freescale/imx/imx51_machdep.c37
-rw-r--r--sys/arm/freescale/imx/imx53_machdep.c37
-rw-r--r--sys/arm/freescale/imx/imx6_machdep.c38
-rw-r--r--sys/arm/freescale/imx/std.imx511
-rw-r--r--sys/arm/freescale/imx/std.imx531
-rw-r--r--sys/arm/freescale/imx/std.imx61
-rw-r--r--sys/arm/freescale/vybrid/std.vybrid1
-rw-r--r--sys/arm/include/asm.h76
-rw-r--r--sys/arm/include/cpuconf.h23
-rw-r--r--sys/arm/include/db_machdep.h2
-rw-r--r--sys/arm/include/frame.h72
-rw-r--r--sys/arm/include/intr.h8
-rw-r--r--sys/arm/include/machdep.h3
-rw-r--r--sys/arm/include/pcb.h39
-rw-r--r--sys/arm/include/smp.h2
-rw-r--r--sys/arm/include/sysreg.h26
-rw-r--r--sys/arm/lpc/lpc_intc.c42
-rw-r--r--sys/arm/mv/mpic.c2
-rw-r--r--sys/arm/mv/std-pj4b.mv1
-rw-r--r--sys/arm/rockchip/std.rk30xx1
-rw-r--r--sys/arm/samsung/exynos/std.exynos52501
-rw-r--r--sys/arm/samsung/exynos/std.exynos54201
-rw-r--r--sys/arm/ti/aintc.c36
-rw-r--r--sys/arm/ti/am335x/am335x_usbss.c27
-rw-r--r--sys/arm/ti/std.ti1
-rw-r--r--sys/arm/ti/ti_gpio.c537
-rw-r--r--sys/arm/ti/ti_gpio.h17
-rw-r--r--sys/arm/ti/ti_i2c.c2
-rw-r--r--sys/arm/ti/ti_sdhci.c57
-rw-r--r--sys/arm/ti/ti_wdt.c2
-rw-r--r--sys/arm/xilinx/std.zynq71
-rw-r--r--sys/boot/amd64/boot1.efi/Makefile2
-rwxr-xr-xsys/boot/amd64/boot1.efi/generate-fat.sh4
-rw-r--r--sys/boot/amd64/efi/Makefile2
-rw-r--r--sys/boot/arm/uboot/Makefile2
-rw-r--r--sys/boot/common/console.c29
-rw-r--r--sys/boot/common/loader.88
-rw-r--r--sys/boot/fdt/dts/arm/am335x.dtsi2
-rw-r--r--sys/boot/fdt/dts/arm/rpi.dts11
-rw-r--r--sys/boot/forth/brand.4th.82
-rw-r--r--sys/boot/forth/delay.4th.82
-rw-r--r--sys/boot/forth/loader.conf1
-rw-r--r--sys/boot/forth/menu.4th.84
-rw-r--r--sys/boot/forth/menusets.4th.84
-rw-r--r--sys/boot/forth/version.4th.84
-rw-r--r--sys/boot/i386/libi386/spinconsole.c2
-rw-r--r--sys/boot/powerpc/uboot/Makefile2
-rw-r--r--sys/boot/uboot/common/main.c9
-rw-r--r--sys/cam/ctl/ctl.c461
-rw-r--r--sys/cam/ctl/ctl.h1
-rw-r--r--sys/cam/ctl/ctl_backend.c46
-rw-r--r--sys/cam/ctl/ctl_backend.h9
-rw-r--r--sys/cam/ctl/ctl_backend_block.c44
-rw-r--r--sys/cam/ctl/ctl_backend_ramdisk.c26
-rw-r--r--sys/cam/ctl/ctl_frontend.c84
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c4
-rw-r--r--sys/cam/ctl/ctl_frontend_internal.c8
-rw-r--r--sys/cam/ctl/ctl_tpc.c49
-rw-r--r--sys/cam/ctl/ctl_tpc.h3
-rw-r--r--sys/cam/ctl/ctl_tpc_local.c5
-rw-r--r--sys/cam/ctl/scsi_ctl.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c10
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c11
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c573
-rw-r--r--sys/cddl/dev/dtrace/amd64/dtrace_subr.c4
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_subr.c4
-rw-r--r--sys/cddl/dev/dtrace/mips/dtrace_subr.c5
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_subr.c5
-rw-r--r--sys/conf/NOTES22
-rw-r--r--sys/conf/files80
-rw-r--r--sys/conf/newvers.sh6
-rw-r--r--sys/conf/options7
-rw-r--r--sys/dev/ahci/ahci.c24
-rw-r--r--sys/dev/ahci/ahci.h3
-rw-r--r--sys/dev/ath/if_ath_sysctl.c10
-rw-r--r--sys/dev/beri/virtio/virtio.c3
-rw-r--r--sys/dev/bge/if_bge.c6
-rw-r--r--sys/dev/cpuctl/cpuctl.c2
-rw-r--r--sys/dev/fdt/fdt_common.c11
-rw-r--r--sys/dev/fxp/if_fxp.c112
-rw-r--r--sys/dev/fxp/if_fxpreg.h2
-rw-r--r--sys/dev/fxp/if_fxpvar.h3
-rw-r--r--sys/dev/gpio/gpio_if.m4
-rw-r--r--sys/dev/ieee488/ibfoo.c1127
-rw-r--r--sys/dev/ieee488/ibfoo_int.h147
-rw-r--r--sys/dev/ieee488/pcii.c255
-rw-r--r--sys/dev/ieee488/tnt4882.c320
-rw-r--r--sys/dev/ieee488/tnt4882.h77
-rw-r--r--sys/dev/ieee488/ugpib.h155
-rw-r--r--sys/dev/ieee488/upd7210.c369
-rw-r--r--sys/dev/ieee488/upd7210.h237
-rw-r--r--sys/dev/ipmi/ipmi_kcs.c13
-rw-r--r--sys/dev/isci/isci_controller.c2
-rw-r--r--sys/dev/isci/isci_sysctl.c5
-rw-r--r--sys/dev/iscsi/iscsi.c4
-rw-r--r--sys/dev/iwn/if_iwn.c13
-rw-r--r--sys/dev/mmc/mmc.c37
-rw-r--r--sys/dev/ofw/ofw_cpu.c14
-rw-r--r--sys/dev/pci/pci.c29
-rw-r--r--sys/dev/sdhci/sdhci.c44
-rw-r--r--sys/dev/sdhci/sdhci.h7
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c1
-rw-r--r--sys/dev/usb/usbdevs3
-rw-r--r--sys/dev/vt/hw/efifb/efifb.c53
-rw-r--r--sys/dev/vt/hw/vga/vt_vga.c55
-rw-r--r--sys/dev/vt/vt.h1
-rw-r--r--sys/dev/vt/vt_core.c4
-rw-r--r--sys/dev/wpi/if_wpi.c30
-rw-r--r--sys/dev/wpi/if_wpireg.h2
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c4
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/fs/nandfs/nandfs_vnops.c2
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c6
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c3
-rw-r--r--sys/fs/nfs/nfsport.h18
-rw-r--r--sys/fs/nfsclient/nfs.h18
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c2
-rw-r--r--sys/fs/nfsclient/nfs_clport.c2
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c11
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c14
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c9
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c125
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c6
-rw-r--r--sys/geom/sched/README26
-rw-r--r--sys/geom/sched/g_sched.c170
-rw-r--r--sys/geom/sched/g_sched.h13
-rw-r--r--sys/geom/sched/gs_rr.c12
-rw-r--r--sys/geom/sched/subr_disk.c226
-rw-r--r--sys/i386/i386/trap.c2
-rw-r--r--sys/i386/xen/clock.c2
-rw-r--r--sys/kern/kern_sig.c3
-rw-r--r--sys/kern/subr_fattime.c2
-rw-r--r--sys/kern/uipc_sockbuf.c21
-rw-r--r--sys/kern/uipc_socket.c9
-rw-r--r--sys/kern/vfs_default.c37
-rw-r--r--sys/kern/vfs_vnops.c2
-rw-r--r--sys/mips/beri/beri_machdep.c4
-rw-r--r--sys/mips/mips/trap.c3
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/cryptodev/Makefile2
-rw-r--r--sys/modules/dtrace/Makefile1
-rw-r--r--sys/modules/dtrace/dtnfsclient/Makefile17
-rw-r--r--sys/modules/dtrace/dtraceall/dtraceall.c3
-rw-r--r--sys/modules/geom/geom_sched/gs_sched/Makefile2
-rw-r--r--sys/modules/geom/geom_sched/gsched_rr/Makefile2
-rw-r--r--sys/modules/if_gif/Makefile6
-rw-r--r--sys/modules/nfs_common/Makefile8
-rw-r--r--sys/modules/nfsclient/Makefile32
-rw-r--r--sys/modules/nfsserver/Makefile12
-rw-r--r--sys/net/if_gif.c2
-rw-r--r--sys/net/if_gif.h10
-rw-r--r--sys/net/if_gre.c10
-rw-r--r--sys/net/if_gre.h9
-rw-r--r--sys/net/if_stf.c6
-rw-r--r--sys/net/if_stf.h38
-rw-r--r--sys/net80211/ieee80211_output.c2
-rw-r--r--sys/net80211/ieee80211_power.c21
-rw-r--r--sys/net80211/ieee80211_proto.h1
-rw-r--r--sys/net80211/ieee80211_scan.c59
-rw-r--r--sys/net80211/ieee80211_sta.c33
-rw-r--r--sys/netinet/in_gif.c9
-rw-r--r--sys/netinet/in_gif.h44
-rw-r--r--sys/netinet/in_systm.h7
-rw-r--r--sys/netinet/ip_gre.c5
-rw-r--r--sys/netinet/ip_icmp.c2
-rw-r--r--sys/netinet/ip_icmp.h2
-rw-r--r--sys/netinet/sctp_usrreq.c23
-rw-r--r--sys/netinet/sctputil.c15
-rw-r--r--sys/netinet6/in6_gif.c9
-rw-r--r--sys/netinet6/in6_gif.h44
-rw-r--r--sys/netinet6/ip6_gre.c5
-rw-r--r--sys/netipsec/ipsec.c27
-rw-r--r--sys/netipsec/ipsec.h23
-rw-r--r--sys/netipsec/key.c295
-rw-r--r--sys/netipsec/key_debug.c4
-rw-r--r--sys/nfs/bootp_subr.c3
-rw-r--r--sys/nfs/nfs_common.c407
-rw-r--r--sys/nfsclient/nfs_bio.c1794
-rw-r--r--sys/nfsclient/nfs_kdtrace.c542
-rw-r--r--sys/nfsclient/nfs_krpc.c887
-rw-r--r--sys/nfsclient/nfs_nfsiod.c346
-rw-r--r--sys/nfsclient/nfs_node.c276
-rw-r--r--sys/nfsclient/nfs_subs.c1140
-rw-r--r--sys/nfsclient/nfs_vfsops.c1582
-rw-r--r--sys/nfsclient/nfs_vnops.c3544
-rw-r--r--sys/nfsserver/nfs_fha_old.c265
-rw-r--r--sys/nfsserver/nfs_serv.c3767
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c545
-rw-r--r--sys/nfsserver/nfs_srvsubs.c1418
-rw-r--r--sys/powerpc/aim/trap.c2
-rw-r--r--sys/sys/dtrace_bsd.h4
-rw-r--r--sys/sys/mbuf.h5
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/sem.h4
-rw-r--r--sys/sys/time.h2
-rw-r--r--sys/sys/vnode.h1
-rw-r--r--sys/teken/libteken/teken.32
-rw-r--r--sys/ufs/ufs/ufs_vnops.c4
-rw-r--r--sys/vm/vm_page.c6
-rw-r--r--sys/vm/vm_page.h38
269 files changed, 6023 insertions, 22507 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 4880c91..67842cf 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -614,7 +614,8 @@ trap_check(struct trapframe *frame)
{
#ifdef KDTRACE_HOOKS
- if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
+ if (dtrace_trap_func != NULL &&
+ (*dtrace_trap_func)(frame, frame->tf_trapno) != 0)
return;
#endif
trap(frame);
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index d1220b6..9b697f0 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -215,7 +215,7 @@ hint.atkbd.0.irq="1"
# Options for atkbd:
options ATKBD_DFLT_KEYMAP # specify the built-in keymap
-makeoptions ATKBD_DFLT_KEYMAP=jp.106
+makeoptions ATKBD_DFLT_KEYMAP=fr.dvorak
# `flags' for atkbd:
# 0x01 Force detection of keyboard, else we always assume a keyboard
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index 0f19110..8a8c3f4 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -358,6 +358,8 @@ void vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo,
void *kaddr, size_t len);
void vm_copyout(struct vm *vm, int vcpuid, const void *kaddr,
struct vm_copyinfo *copyinfo, size_t len);
+
+int vcpu_trace_exceptions(struct vm *vm, int vcpuid);
#endif /* KERNEL */
#define VM_MAXCPU 16 /* maximum virtual cpus */
diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c
index 753799a..7d75046 100644
--- a/sys/amd64/vmm/amd/svm.c
+++ b/sys/amd64/vmm/amd/svm.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/specialreg.h>
#include <machine/smp.h>
#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
#include <machine/vmm_instruction_emul.h>
#include "vmm_lapic.h"
@@ -429,8 +430,24 @@ vmcb_init(struct svm_softc *sc, int vcpu, uint64_t iopm_base_pa,
svm_enable_intercept(sc, vcpu, VMCB_CR_INTCPT, mask);
}
- /* Intercept Machine Check exceptions. */
- svm_enable_intercept(sc, vcpu, VMCB_EXC_INTCPT, BIT(IDT_MC));
+
+ /*
+ * Intercept everything when tracing guest exceptions otherwise
+ * just intercept machine check exception.
+ */
+ if (vcpu_trace_exceptions(sc->vm, vcpu)) {
+ for (n = 0; n < 32; n++) {
+ /*
+ * Skip unimplemented vectors in the exception bitmap.
+ */
+ if (n == 2 || n == 9) {
+ continue;
+ }
+ svm_enable_intercept(sc, vcpu, VMCB_EXC_INTCPT, BIT(n));
+ }
+ } else {
+ svm_enable_intercept(sc, vcpu, VMCB_EXC_INTCPT, BIT(IDT_MC));
+ }
/* Intercept various events (for e.g. I/O, MSR and CPUID accesses) */
svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_IO);
@@ -1176,9 +1193,10 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
struct vmcb_state *state;
struct vmcb_ctrl *ctrl;
struct svm_regctx *ctx;
+ struct vm_exception exception;
uint64_t code, info1, info2, val;
uint32_t eax, ecx, edx;
- int handled;
+ int error, errcode_valid, handled, idtvec, reflect;
bool retu;
ctx = svm_get_guest_regctx(svm_sc, vcpu);
@@ -1237,8 +1255,78 @@ svm_vmexit(struct svm_softc *svm_sc, int vcpu, struct vm_exit *vmexit)
case VMCB_EXIT_NMI: /* external NMI */
handled = 1;
break;
- case VMCB_EXIT_MC: /* machine check */
+ case 0x40 ... 0x5F:
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_EXCEPTION, 1);
+ reflect = 1;
+ idtvec = code - 0x40;
+ switch (idtvec) {
+ case IDT_MC:
+ /*
+ * Call the machine check handler by hand. Also don't
+ * reflect the machine check back into the guest.
+ */
+ reflect = 0;
+ VCPU_CTR0(svm_sc->vm, vcpu, "Vectoring to MCE handler");
+ __asm __volatile("int $18");
+ break;
+ case IDT_PF:
+ error = svm_setreg(svm_sc, vcpu, VM_REG_GUEST_CR2,
+ info2);
+ KASSERT(error == 0, ("%s: error %d updating cr2",
+ __func__, error));
+ /* fallthru */
+ case IDT_NP:
+ case IDT_SS:
+ case IDT_GP:
+ case IDT_AC:
+ case IDT_TS:
+ errcode_valid = 1;
+ break;
+
+ case IDT_DF:
+ errcode_valid = 1;
+ info1 = 0;
+ break;
+
+ case IDT_BP:
+ case IDT_OF:
+ case IDT_BR:
+ /*
+ * The 'nrip' field is populated for INT3, INTO and
+ * BOUND exceptions and this also implies that
+ * 'inst_length' is non-zero.
+ *
+ * Reset 'inst_length' to zero so the guest %rip at
+ * event injection is identical to what it was when
+ * the exception originally happened.
+ */
+ VCPU_CTR2(svm_sc->vm, vcpu, "Reset inst_length from %d "
+ "to zero before injecting exception %d",
+ vmexit->inst_length, idtvec);
+ vmexit->inst_length = 0;
+ /* fallthru */
+ default:
+ errcode_valid = 0;
+ break;
+ }
+ KASSERT(vmexit->inst_length == 0, ("invalid inst_length (%d) "
+ "when reflecting exception %d into guest",
+ vmexit->inst_length, idtvec));
+
+ if (reflect) {
+ /* Reflect the exception back into the guest */
+ exception.vector = idtvec;
+ exception.error_code_valid = errcode_valid;
+ exception.error_code = errcode_valid ? info1 : 0;
+ VCPU_CTR2(svm_sc->vm, vcpu, "Reflecting exception "
+ "%d/%#x into the guest", exception.vector,
+ exception.error_code);
+ error = vm_inject_exception(svm_sc->vm, vcpu,
+ &exception);
+ KASSERT(error == 0, ("%s: vm_inject_exception error %d",
+ __func__, error));
+ }
+ handled = 1;
break;
case VMCB_EXIT_MSR: /* MSR access. */
eax = state->rax;
diff --git a/sys/amd64/vmm/intel/vmcs.c b/sys/amd64/vmm/intel/vmcs.c
index 51e5c2c..ae4d9db 100644
--- a/sys/amd64/vmm/intel/vmcs.c
+++ b/sys/amd64/vmm/intel/vmcs.c
@@ -332,7 +332,6 @@ vmcs_init(struct vmcs *vmcs)
int error, codesel, datasel, tsssel;
u_long cr0, cr4, efer;
uint64_t pat, fsbase, idtrbase;
- uint32_t exc_bitmap;
codesel = vmm_get_host_codesel();
datasel = vmm_get_host_datasel();
@@ -417,11 +416,6 @@ vmcs_init(struct vmcs *vmcs)
if ((error = vmwrite(VMCS_HOST_RIP, (u_long)vmx_exit_guest)) != 0)
goto done;
- /* exception bitmap */
- exc_bitmap = 1 << IDT_MC;
- if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0)
- goto done;
-
/* link pointer */
if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0)
goto done;
diff --git a/sys/amd64/vmm/intel/vmcs.h b/sys/amd64/vmm/intel/vmcs.h
index 6122de5..6d78a69 100644
--- a/sys/amd64/vmm/intel/vmcs.h
+++ b/sys/amd64/vmm/intel/vmcs.h
@@ -321,7 +321,7 @@ vmcs_write(uint32_t encoding, uint64_t val)
#define EXIT_REASON_MTF 37
#define EXIT_REASON_MONITOR 39
#define EXIT_REASON_PAUSE 40
-#define EXIT_REASON_MCE 41
+#define EXIT_REASON_MCE_DURING_ENTRY 41
#define EXIT_REASON_TPR 43
#define EXIT_REASON_APIC_ACCESS 44
#define EXIT_REASON_VIRTUALIZED_EOI 45
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index c855697..c3dd04e 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -283,8 +283,8 @@ exit_reason_to_str(int reason)
return "monitor";
case EXIT_REASON_PAUSE:
return "pause";
- case EXIT_REASON_MCE:
- return "mce";
+ case EXIT_REASON_MCE_DURING_ENTRY:
+ return "mce-during-entry";
case EXIT_REASON_TPR:
return "tpr";
case EXIT_REASON_APIC_ACCESS:
@@ -821,6 +821,7 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
int i, error;
struct vmx *vmx;
struct vmcs *vmcs;
+ uint32_t exc_bitmap;
vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
if ((uintptr_t)vmx & PAGE_MASK) {
@@ -911,6 +912,14 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
error += vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
error += vmwrite(VMCS_MSR_BITMAP, vtophys(vmx->msr_bitmap));
error += vmwrite(VMCS_VPID, vpid[i]);
+
+ /* exception bitmap */
+ if (vcpu_trace_exceptions(vm, i))
+ exc_bitmap = 0xffffffff;
+ else
+ exc_bitmap = 1 << IDT_MC;
+ error += vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap);
+
if (virtual_interrupt_delivery) {
error += vmwrite(VMCS_APIC_ACCESS, APIC_ACCESS_ADDRESS);
error += vmwrite(VMCS_VIRTUAL_APIC,
@@ -2056,8 +2065,9 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
struct vlapic *vlapic;
struct vm_inout_str *vis;
struct vm_task_switch *ts;
+ struct vm_exception vmexc;
uint32_t eax, ecx, edx, idtvec_info, idtvec_err, intr_info, inst_info;
- uint32_t intr_type, reason;
+ uint32_t intr_type, intr_vec, reason;
uint64_t exitintinfo, qual, gpa;
bool retu;
@@ -2074,6 +2084,18 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
vmm_stat_incr(vmx->vm, vcpu, VMEXIT_COUNT, 1);
/*
+ * VM-entry failures during or after loading guest state.
+ *
+ * These VM-exits are uncommon but must be handled specially
+ * as most VM-exit fields are not populated as usual.
+ */
+ if (__predict_false(reason == EXIT_REASON_MCE_DURING_ENTRY)) {
+ VCPU_CTR0(vmx->vm, vcpu, "Handling MCE during VM-entry");
+ __asm __volatile("int $18");
+ return (1);
+ }
+
+ /*
* VM exits that can be triggered during event delivery need to
* be handled specially by re-injecting the event if the IDT
* vectoring information field's valid bit is set.
@@ -2305,6 +2327,9 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
KASSERT((intr_info & VMCS_INTR_VALID) != 0,
("VM exit interruption info invalid: %#x", intr_info));
+ intr_vec = intr_info & 0xff;
+ intr_type = intr_info & VMCS_INTR_T_MASK;
+
/*
* If Virtual NMIs control is 1 and the VM-exit is due to a
* fault encountered during the execution of IRET then we must
@@ -2315,16 +2340,55 @@ vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit)
* See "Information for VM Exits Due to Vectored Events".
*/
if ((idtvec_info & VMCS_IDT_VEC_VALID) == 0 &&
- (intr_info & 0xff) != IDT_DF &&
+ (intr_vec != IDT_DF) &&
(intr_info & EXIT_QUAL_NMIUDTI) != 0)
vmx_restore_nmi_blocking(vmx, vcpu);
/*
* The NMI has already been handled in vmx_exit_handle_nmi().
*/
- if ((intr_info & VMCS_INTR_T_MASK) == VMCS_INTR_T_NMI)
+ if (intr_type == VMCS_INTR_T_NMI)
return (1);
- break;
+
+ /*
+ * Call the machine check handler by hand. Also don't reflect
+ * the machine check back into the guest.
+ */
+ if (intr_vec == IDT_MC) {
+ VCPU_CTR0(vmx->vm, vcpu, "Vectoring to MCE handler");
+ __asm __volatile("int $18");
+ return (1);
+ }
+
+ if (intr_vec == IDT_PF) {
+ error = vmxctx_setreg(vmxctx, VM_REG_GUEST_CR2, qual);
+ KASSERT(error == 0, ("%s: vmxctx_setreg(cr2) error %d",
+ __func__, error));
+ }
+
+ /*
+ * Software exceptions exhibit trap-like behavior. This in
+ * turn requires populating the VM-entry instruction length
+ * so that the %rip in the trap frame is past the INT3/INTO
+ * instruction.
+ */
+ if (intr_type == VMCS_INTR_T_SWEXCEPTION)
+ vmcs_write(VMCS_ENTRY_INST_LENGTH, vmexit->inst_length);
+
+ /* Reflect all other exceptions back into the guest */
+ bzero(&vmexc, sizeof(struct vm_exception));
+ vmexc.vector = intr_vec;
+ if (intr_info & VMCS_INTR_DEL_ERRCODE) {
+ vmexc.error_code_valid = 1;
+ vmexc.error_code = vmcs_read(VMCS_EXIT_INTR_ERRCODE);
+ }
+ VCPU_CTR2(vmx->vm, vcpu, "Reflecting exception %d/%#x into "
+ "the guest", vmexc.vector, vmexc.error_code);
+ error = vm_inject_exception(vmx->vm, vcpu, &vmexc);
+ KASSERT(error == 0, ("%s: vm_inject_exception error %d",
+ __func__, error));
+ return (1);
+
case EXIT_REASON_EPT_FAULT:
/*
* If 'gpa' lies within the address space allocated to
diff --git a/sys/amd64/vmm/intel/vmx_msr.c b/sys/amd64/vmm/intel/vmx_msr.c
index 746ca73..f6bbf2a 100644
--- a/sys/amd64/vmm/intel/vmx_msr.c
+++ b/sys/amd64/vmm/intel/vmx_msr.c
@@ -376,9 +376,31 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
int
vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu)
{
- int error = 0;
-
+ uint64_t changed;
+ int error;
+
+ error = 0;
switch (num) {
+ case MSR_IA32_MISC_ENABLE:
+ changed = val ^ misc_enable;
+ /*
+ * If the host has disabled the NX feature then the guest
+ * also cannot use it. However, a Linux guest will try to
+ * enable the NX feature by writing to the MISC_ENABLE MSR.
+ *
+ * This can be safely ignored because the memory management
+ * code looks at CPUID.80000001H:EDX.NX to check if the
+ * functionality is actually enabled.
+ */
+ changed &= ~(1UL << 34);
+
+ /*
+ * Punt to userspace if any other bits are being modified.
+ */
+ if (changed)
+ error = EINVAL;
+
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/amd64/vmm/io/vatpic.c b/sys/amd64/vmm/io/vatpic.c
index c6d4590..74a7027 100644
--- a/sys/amd64/vmm/io/vatpic.c
+++ b/sys/amd64/vmm/io/vatpic.c
@@ -112,6 +112,16 @@ struct vatpic {
static void vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate);
+static __inline bool
+master_atpic(struct vatpic *vatpic, struct atpic *atpic)
+{
+
+ if (atpic == &vatpic->atpic[0])
+ return (true);
+ else
+ return (false);
+}
+
static __inline int
vatpic_get_highest_isrpin(struct atpic *atpic)
{
@@ -250,6 +260,7 @@ vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
atpic->mask = 0;
atpic->lowprio = 7;
atpic->rd_cmd_reg = 0;
+ atpic->poll = 0;
if ((val & ICW1_SNGL) != 0) {
VATPIC_CTR0(vatpic, "vatpic cascade mode required");
@@ -301,6 +312,15 @@ vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
if ((val & ICW4_AEOI) != 0)
atpic->aeoi = true;
+ if ((val & ICW4_SFNM) != 0) {
+ if (master_atpic(vatpic, atpic)) {
+ atpic->sfn = true;
+ } else {
+ VATPIC_CTR1(vatpic, "Ignoring special fully nested "
+ "mode on slave atpic: %#x", val);
+ }
+ }
+
atpic->icw_num = 0;
atpic->ready = true;
@@ -354,11 +374,17 @@ vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val)
{
VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val);
- atpic->poll = ((val & OCW3_P) != 0);
+ if (val & OCW3_ESMM) {
+ VATPIC_CTR0(vatpic, "atpic special mask mode not implemented");
+ return (-1);
+ }
if (val & OCW3_RR) {
/* read register command */
atpic->rd_cmd_reg = val & OCW3_RIS;
+
+ /* Polling mode */
+ atpic->poll = ((val & OCW3_P) != 0);
}
return (0);
@@ -578,12 +604,19 @@ static int
vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port,
int bytes, uint32_t *eax)
{
+ int pin;
+
VATPIC_LOCK(vatpic);
if (atpic->poll) {
- VATPIC_CTR0(vatpic, "vatpic polled mode not supported");
- VATPIC_UNLOCK(vatpic);
- return (-1);
+ atpic->poll = 0;
+ pin = vatpic_get_highest_irrpin(atpic);
+ if (pin >= 0) {
+ vatpic_pin_accepted(atpic, pin);
+ *eax = 0x80 | pin;
+ } else {
+ *eax = 0;
+ }
} else {
if (port & ICU_IMR_OFFSET) {
/* read interrrupt mask register */
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index e7fbada..d9cb6f3 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -207,6 +207,11 @@ static int vmm_ipinum;
SYSCTL_INT(_hw_vmm, OID_AUTO, ipinum, CTLFLAG_RD, &vmm_ipinum, 0,
"IPI vector used for vcpu notifications");
+static int trace_guest_exceptions;
+SYSCTL_INT(_hw_vmm, OID_AUTO, trace_guest_exceptions, CTLFLAG_RDTUN,
+ &trace_guest_exceptions, 0,
+ "Trap into hypervisor on all guest exceptions and reflect them back");
+
static void
vcpu_cleanup(struct vm *vm, int i, bool destroy)
{
@@ -250,6 +255,13 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create)
vmm_stat_init(vcpu->stats);
}
+int
+vcpu_trace_exceptions(struct vm *vm, int vcpuid)
+{
+
+ return (trace_guest_exceptions);
+}
+
struct vm_exit *
vm_exitinfo(struct vm *vm, int cpuid)
{
diff --git a/sys/arm/allwinner/a20/std.a20 b/sys/arm/allwinner/a20/std.a20
index f582e91..7beb2bd 100644
--- a/sys/arm/allwinner/a20/std.a20
+++ b/sys/arm/allwinner/a20/std.a20
@@ -3,6 +3,7 @@
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoption ARM_LITTLE_ENDIAN
# Physical memory starts at 0x40200000. We assume images are loaded at
diff --git a/sys/arm/allwinner/std.a10 b/sys/arm/allwinner/std.a10
index 11ef732..338395d 100644
--- a/sys/arm/allwinner/std.a10
+++ b/sys/arm/allwinner/std.a10
@@ -3,6 +3,7 @@
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoption ARM_LITTLE_ENDIAN
# Physical memory starts at 0x40200000. We assume images are loaded at
diff --git a/sys/arm/altera/socfpga/std.socfpga b/sys/arm/altera/socfpga/std.socfpga
index c6607a5..2bc45b9 100644
--- a/sys/arm/altera/socfpga/std.socfpga
+++ b/sys/arm/altera/socfpga/std.socfpga
@@ -4,6 +4,7 @@ makeoption ARM_LITTLE_ENDIAN
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
options PHYSADDR=0x00000000
diff --git a/sys/arm/arm/db_trace.c b/sys/arm/arm/db_trace.c
index e0d7552..04ab565 100644
--- a/sys/arm/arm/db_trace.c
+++ b/sys/arm/arm/db_trace.c
@@ -345,9 +345,16 @@ db_unwind_tab(struct unwind_state *state)
/*
* The program counter was not updated, load it from the link register.
*/
- if (state->registers[PC] == 0)
+ if (state->registers[PC] == 0) {
state->registers[PC] = state->registers[LR];
+ /*
+ * If the program counter changed, flag it in the update mask.
+ */
+ if (state->start_pc != state->registers[PC])
+ state->update_mask |= 1 << PC;
+ }
+
return 0;
}
@@ -602,14 +609,14 @@ db_trace_thread(struct thread *thr, int count)
ctx = kdb_thr_ctx(thr);
#ifdef __ARM_EABI__
- state.registers[FP] = ctx->un_32.pcb32_r11;
- state.registers[SP] = ctx->un_32.pcb32_sp;
- state.registers[LR] = ctx->un_32.pcb32_lr;
- state.registers[PC] = ctx->un_32.pcb32_pc;
+ state.registers[FP] = ctx->pcb_regs.sf_r11;
+ state.registers[SP] = ctx->pcb_regs.sf_sp;
+ state.registers[LR] = ctx->pcb_regs.sf_lr;
+ state.registers[PC] = ctx->pcb_regs.sf_pc;
db_stack_trace_cmd(&state);
#else
- db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE);
+ db_stack_trace_cmd(ctx->pcb_regs.sf_r11, -1, TRUE);
#endif
} else
db_trace_self();
diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c
index 19c19c90..61d6eb5 100644
--- a/sys/arm/arm/dump_machdep.c
+++ b/sys/arm/arm/dump_machdep.c
@@ -160,11 +160,13 @@ static int
cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
{
struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_paddr_t pa;
+ vm_paddr_t a, pa;
+ void *va;
uint32_t pgs;
size_t counter, sz, chunk;
- int c, error;
+ int i, c, error;
+ va = 0;
error = 0; /* catch case in which chunk size is 0 */
counter = 0;
pgs = mdp->md_size / PAGE_SIZE;
@@ -194,16 +196,14 @@ cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
printf(" %d", pgs * PAGE_SIZE);
counter &= (1<<24) - 1;
}
- if (pa == (pa & L1_ADDR_BITS)) {
- pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
- cpu_tlb_flushID_SE(0);
- cpu_cpwait();
+ for (i = 0; i < chunk; i++) {
+ a = pa + i * PAGE_SIZE;
+ va = pmap_kenter_temporary(trunc_page(a), i);
}
#ifdef SW_WATCHDOG
wdog_kern_pat(WD_LASTVAL);
#endif
- error = dump_write(di,
- (void *)(pa - (pa & L1_ADDR_BITS)),0, dumplo, sz);
+ error = dump_write(di, va, 0, dumplo, sz);
if (error)
break;
dumplo += sz;
diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S
index 5cef965..3886968 100644
--- a/sys/arm/arm/exception.S
+++ b/sys/arm/arm/exception.S
@@ -241,26 +241,26 @@ __FBSDID("$FreeBSD$");
#define UNWINDSVCFRAME
#endif
-#define DO_AST \
- ldr r0, [sp] /* Get the SPSR from stack */ ;\
- mrs r4, cpsr /* save CPSR */ ;\
- orr r1, r4, #(PSR_I|PSR_F) ;\
- msr cpsr_c, r1 /* Disable interrupts */ ;\
- and r0, r0, #(PSR_MODE) /* Returning to USR mode? */ ;\
- teq r0, #(PSR_USR32_MODE) ;\
- bne 2f /* Nope, get out now */ ;\
- bic r4, r4, #(PSR_I|PSR_F) ;\
-1: GET_CURTHREAD_PTR(r5) ;\
- ldr r1, [r5, #(TD_FLAGS)] ;\
- and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED) ;\
- teq r1, #0x00000000 ;\
- beq 2f /* Nope. Just bail */ ;\
- msr cpsr_c, r4 /* Restore interrupts */ ;\
- mov r0, sp ;\
- bl _C_LABEL(ast) /* ast(frame) */ ;\
- orr r0, r4, #(PSR_I|PSR_F) ;\
- msr cpsr_c, r0 ;\
- b 1b ;\
+#define DO_AST \
+ ldr r0, [sp]; /* Get the SPSR from stack */ \
+ mrs r4, cpsr; /* save CPSR */ \
+ orr r1, r4, #(PSR_I|PSR_F); \
+ msr cpsr_c, r1; /* Disable interrupts */ \
+ and r0, r0, #(PSR_MODE); /* Returning to USR mode? */ \
+ teq r0, #(PSR_USR32_MODE); \
+ bne 2f; /* Nope, get out now */ \
+ bic r4, r4, #(PSR_I|PSR_F); \
+1: GET_CURTHREAD_PTR(r5); \
+ ldr r1, [r5, #(TD_FLAGS)]; \
+ and r1, r1, #(TDF_ASTPENDING|TDF_NEEDRESCHED); \
+ teq r1, #0; \
+ beq 2f; /* Nope. Just bail */ \
+ msr cpsr_c, r4; /* Restore interrupts */ \
+ mov r0, sp; \
+ bl _C_LABEL(ast); /* ast(frame) */ \
+ orr r0, r4, #(PSR_I|PSR_F); \
+ msr cpsr_c, r0; \
+ b 1b; \
2:
@@ -320,7 +320,8 @@ ASENTRY_NP(prefetch_abort_entry)
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
adr lr, exception_exit /* Return from handler via standard */
mov r0, sp /* exception exit routine. Pass the */
- b prefetch_abort_handler /* trapframe to the handler. */
+ mov r1, #1 /* Type flag */
+ b _C_LABEL(abort_handler)
END(prefetch_abort_entry)
/*
@@ -337,9 +338,10 @@ ASENTRY_NP(data_abort_entry)
#endif
sub lr, lr, #8 /* Adjust the lr. Transition to scv32 */
PUSHFRAMEINSVC /* mode stack, build trapframe there. */
- adr lr, exception_exit /* Return from handler via standard */
- mov r0, sp /* exception exit routine. Pass the */
- b data_abort_handler /* trapframe to the handler. */
+ adr lr, exception_exit /* Exception exit routine */
+ mov r0, sp /* Trapframe to the handler */
+ mov r1, #0 /* Type flag */
+ b _C_LABEL(abort_handler)
END(data_abort_entry)
/*
diff --git a/sys/arm/arm/gdb_machdep.c b/sys/arm/arm/gdb_machdep.c
index 11b9c0d..8cc7a19 100644
--- a/sys/arm/arm/gdb_machdep.c
+++ b/sys/arm/arm/gdb_machdep.c
@@ -67,22 +67,26 @@ gdb_cpu_getreg(int regnum, size_t *regsz)
}
switch (regnum) {
- case 8: return (&kdb_thrctx->un_32.pcb32_r8);
- case 9: return (&kdb_thrctx->un_32.pcb32_r9);
- case 10: return (&kdb_thrctx->un_32.pcb32_r10);
- case 11: return (&kdb_thrctx->un_32.pcb32_r11);
- case 12: return (&kdb_thrctx->un_32.pcb32_r12);
- case 13: stacktest = kdb_thrctx->un_32.pcb32_sp + 5 * 4;
+ case 4: return (&kdb_thrctx->pcb_regs.sf_r4);
+ case 5: return (&kdb_thrctx->pcb_regs.sf_r5);
+ case 6: return (&kdb_thrctx->pcb_regs.sf_r6);
+ case 7: return (&kdb_thrctx->pcb_regs.sf_r7);
+ case 8: return (&kdb_thrctx->pcb_regs.sf_r8);
+ case 9: return (&kdb_thrctx->pcb_regs.sf_r9);
+ case 10: return (&kdb_thrctx->pcb_regs.sf_r10);
+ case 11: return (&kdb_thrctx->pcb_regs.sf_r11);
+ case 12: return (&kdb_thrctx->pcb_regs.sf_r12);
+ case 13: stacktest = kdb_thrctx->pcb_regs.sf_sp + 5 * 4;
return (&stacktest);
case 15:
/*
* On context switch, the PC is not put in the PCB, but
* we can retrieve it from the stack.
*/
- if (kdb_thrctx->un_32.pcb32_sp > KERNBASE) {
- kdb_thrctx->un_32.pcb32_pc = *(register_t *)
- (kdb_thrctx->un_32.pcb32_sp + 4 * 4);
- return (&kdb_thrctx->un_32.pcb32_pc);
+ if (kdb_thrctx->pcb_regs.sf_sp > KERNBASE) {
+ kdb_thrctx->pcb_regs.sf_pc = *(register_t *)
+ (kdb_thrctx->pcb_regs.sf_sp + 4 * 4);
+ return (&kdb_thrctx->pcb_regs.sf_pc);
}
}
diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c
index ab0be4c..ce7b88d 100644
--- a/sys/arm/arm/genassym.c
+++ b/sys/arm/arm/genassym.c
@@ -63,13 +63,18 @@ ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_PAGEDIR, offsetof(struct pcb, pcb_pagedir));
ASSYM(PCB_L1VEC, offsetof(struct pcb, pcb_l1vec));
ASSYM(PCB_PL1VEC, offsetof(struct pcb, pcb_pl1vec));
-ASSYM(PCB_R8, offsetof(struct pcb, un_32.pcb32_r8));
-ASSYM(PCB_R9, offsetof(struct pcb, un_32.pcb32_r9));
-ASSYM(PCB_R10, offsetof(struct pcb, un_32.pcb32_r10));
-ASSYM(PCB_R11, offsetof(struct pcb, un_32.pcb32_r11));
-ASSYM(PCB_R12, offsetof(struct pcb, un_32.pcb32_r12));
-ASSYM(PCB_PC, offsetof(struct pcb, un_32.pcb32_pc));
-ASSYM(PCB_SP, offsetof(struct pcb, un_32.pcb32_sp));
+ASSYM(PCB_R4, offsetof(struct pcb, pcb_regs.sf_r4));
+ASSYM(PCB_R5, offsetof(struct pcb, pcb_regs.sf_r5));
+ASSYM(PCB_R6, offsetof(struct pcb, pcb_regs.sf_r6));
+ASSYM(PCB_R7, offsetof(struct pcb, pcb_regs.sf_r7));
+ASSYM(PCB_R8, offsetof(struct pcb, pcb_regs.sf_r8));
+ASSYM(PCB_R9, offsetof(struct pcb, pcb_regs.sf_r9));
+ASSYM(PCB_R10, offsetof(struct pcb, pcb_regs.sf_r10));
+ASSYM(PCB_R11, offsetof(struct pcb, pcb_regs.sf_r11));
+ASSYM(PCB_R12, offsetof(struct pcb, pcb_regs.sf_r12));
+ASSYM(PCB_SP, offsetof(struct pcb, pcb_regs.sf_sp));
+ASSYM(PCB_LR, offsetof(struct pcb, pcb_regs.sf_lr));
+ASSYM(PCB_PC, offsetof(struct pcb, pcb_regs.sf_pc));
ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
index f1bb014..af667ca 100644
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -99,13 +99,13 @@ __FBSDID("$FreeBSD$");
#define GICD_ICFGR_TRIG_MASK 0x2
struct arm_gic_softc {
+ device_t gic_dev;
struct resource * gic_res[3];
bus_space_tag_t gic_c_bst;
bus_space_tag_t gic_d_bst;
bus_space_handle_t gic_c_bsh;
bus_space_handle_t gic_d_bsh;
uint8_t ver;
- device_t dev;
struct mtx mutex;
uint32_t nirqs;
};
@@ -118,14 +118,14 @@ static struct resource_spec arm_gic_spec[] = {
static struct arm_gic_softc *arm_gic_sc = NULL;
-#define gic_c_read_4(reg) \
- bus_space_read_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg)
-#define gic_c_write_4(reg, val) \
- bus_space_write_4(arm_gic_sc->gic_c_bst, arm_gic_sc->gic_c_bsh, reg, val)
-#define gic_d_read_4(reg) \
- bus_space_read_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg)
-#define gic_d_write_4(reg, val) \
- bus_space_write_4(arm_gic_sc->gic_d_bst, arm_gic_sc->gic_d_bsh, reg, val)
+#define gic_c_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg))
+#define gic_c_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->gic_c_bst, (_sc)->gic_c_bsh, (_reg), (_val))
+#define gic_d_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg))
+#define gic_d_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->gic_d_bst, (_sc)->gic_d_bsh, (_reg), (_val))
static int gic_config_irq(int irq, enum intr_trigger trig,
enum intr_polarity pol);
@@ -158,35 +158,32 @@ arm_gic_probe(device_t dev)
void
gic_init_secondary(void)
{
- int i, nirqs;
+ struct arm_gic_softc *sc = arm_gic_sc;
+ int i;
- /* Get the number of interrupts */
- nirqs = gic_d_read_4(GICD_TYPER);
- nirqs = 32 * ((nirqs & 0x1f) + 1);
-
- for (i = 0; i < nirqs; i += 4)
- gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0);
+ for (i = 0; i < sc->nirqs; i += 4)
+ gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
/* Set all the interrupts to be in Group 0 (secure) */
- for (i = 0; i < nirqs; i += 32) {
- gic_d_write_4(GICD_IGROUPR(i >> 5), 0);
+ for (i = 0; i < sc->nirqs; i += 32) {
+ gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
}
/* Enable CPU interface */
- gic_c_write_4(GICC_CTLR, 1);
+ gic_c_write_4(sc, GICC_CTLR, 1);
/* Set priority mask register. */
- gic_c_write_4(GICC_PMR, 0xff);
+ gic_c_write_4(sc, GICC_PMR, 0xff);
/* Enable interrupt distribution */
- gic_d_write_4(GICD_CTLR, 0x01);
+ gic_d_write_4(sc, GICD_CTLR, 0x01);
/*
* Activate the timer interrupts: virtual, secure, and non-secure.
*/
- gic_d_write_4(GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
- gic_d_write_4(GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
- gic_d_write_4(GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
+ gic_d_write_4(sc, GICD_ISENABLER(27 >> 5), (1UL << (27 & 0x1F)));
+ gic_d_write_4(sc, GICD_ISENABLER(29 >> 5), (1UL << (29 & 0x1F)));
+ gic_d_write_4(sc, GICD_ISENABLER(30 >> 5), (1UL << (30 & 0x1F)));
}
int
@@ -245,13 +242,15 @@ arm_gic_attach(device_t dev)
return (ENXIO);
sc = device_get_softc(dev);
- sc->dev = dev;
if (bus_alloc_resources(dev, arm_gic_spec, sc->gic_res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
+ sc->gic_dev = dev;
+ arm_gic_sc = sc;
+
/* Initialize mutex */
mtx_init(&sc->mutex, "GIC lock", "", MTX_SPIN);
@@ -263,100 +262,81 @@ arm_gic_attach(device_t dev)
sc->gic_c_bst = rman_get_bustag(sc->gic_res[1]);
sc->gic_c_bsh = rman_get_bushandle(sc->gic_res[1]);
- arm_gic_sc = sc;
-
/* Disable interrupt forwarding to the CPU interface */
- gic_d_write_4(GICD_CTLR, 0x00);
+ gic_d_write_4(sc, GICD_CTLR, 0x00);
/* Get the number of interrupts */
- sc->nirqs = gic_d_read_4(GICD_TYPER);
+ sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
/* Set up function pointers */
arm_post_filter = gic_post_filter;
arm_config_irq = gic_config_irq;
- icciidr = gic_c_read_4(GICC_IIDR);
+ icciidr = gic_c_read_4(sc, GICC_IIDR);
device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
icciidr>>20, (icciidr>>16) & 0xF, (icciidr>>12) & 0xf,
(icciidr & 0xfff), sc->nirqs);
/* Set all global interrupts to be level triggered, active low. */
for (i = 32; i < sc->nirqs; i += 16) {
- gic_d_write_4(GICD_ICFGR(i >> 4), 0x00000000);
+ gic_d_write_4(sc, GICD_ICFGR(i >> 4), 0x00000000);
}
/* Disable all interrupts. */
for (i = 32; i < sc->nirqs; i += 32) {
- gic_d_write_4(GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
+ gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
}
for (i = 0; i < sc->nirqs; i += 4) {
- gic_d_write_4(GICD_IPRIORITYR(i >> 2), 0);
- gic_d_write_4(GICD_ITARGETSR(i >> 2), 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
+ gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
+ gic_d_write_4(sc, GICD_ITARGETSR(i >> 2),
+ 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
}
/* Set all the interrupts to be in Group 0 (secure) */
for (i = 0; i < sc->nirqs; i += 32) {
- gic_d_write_4(GICD_IGROUPR(i >> 5), 0);
+ gic_d_write_4(sc, GICD_IGROUPR(i >> 5), 0);
}
/* Enable CPU interface */
- gic_c_write_4(GICC_CTLR, 1);
+ gic_c_write_4(sc, GICC_CTLR, 1);
/* Set priority mask register. */
- gic_c_write_4(GICC_PMR, 0xff);
+ gic_c_write_4(sc, GICC_PMR, 0xff);
/* Enable interrupt distribution */
- gic_d_write_4(GICD_CTLR, 0x01);
+ gic_d_write_4(sc, GICD_CTLR, 0x01);
return (0);
}
-static device_method_t arm_gic_methods[] = {
- DEVMETHOD(device_probe, arm_gic_probe),
- DEVMETHOD(device_attach, arm_gic_attach),
- { 0, 0 }
-};
-
-static driver_t arm_gic_driver = {
- "gic",
- arm_gic_methods,
- sizeof(struct arm_gic_softc),
-};
-
-static devclass_t arm_gic_devclass;
-
-EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
- BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
-EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0,
- BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
-
static void
gic_post_filter(void *arg)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
uintptr_t irq = (uintptr_t) arg;
if (irq > GIC_LAST_IPI)
arm_irq_memory_barrier(irq);
- gic_c_write_4(GICC_EOIR, irq);
+ gic_c_write_4(sc, GICC_EOIR, irq);
}
int
arm_get_next_irq(int last_irq)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
uint32_t active_irq;
- active_irq = gic_c_read_4(GICC_IAR);
+ active_irq = gic_c_read_4(sc, GICC_IAR);
/*
* Immediatly EOIR the SGIs, because doing so requires the other
* bits (ie CPU number), not just the IRQ number, and we do not
* have this information later.
*/
-
if ((active_irq & 0x3ff) <= GIC_LAST_IPI)
- gic_c_write_4(GICC_EOIR, active_irq);
+ gic_c_write_4(sc, GICC_EOIR, active_irq);
active_irq &= 0x3FF;
if (active_irq == 0x3FF) {
@@ -371,29 +351,33 @@ arm_get_next_irq(int last_irq)
void
arm_mask_irq(uintptr_t nb)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
- gic_d_write_4(GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F)));
- gic_c_write_4(GICC_EOIR, nb);
+ gic_d_write_4(sc, GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F)));
+ gic_c_write_4(sc, GICC_EOIR, nb);
}
void
arm_unmask_irq(uintptr_t nb)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
if (nb > GIC_LAST_IPI)
arm_irq_memory_barrier(nb);
- gic_d_write_4(GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F)));
+ gic_d_write_4(sc, GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F)));
}
static int
gic_config_irq(int irq, enum intr_trigger trig,
enum intr_polarity pol)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
+ device_t dev = sc->gic_dev;
uint32_t reg;
uint32_t mask;
/* Function is public-accessible, so validate input arguments */
- if ((irq < 0) || (irq >= arm_gic_sc->nirqs))
+ if ((irq < 0) || (irq >= sc->nirqs))
goto invalid_args;
if ((trig != INTR_TRIGGER_EDGE) && (trig != INTR_TRIGGER_LEVEL) &&
(trig != INTR_TRIGGER_CONFORM))
@@ -402,9 +386,9 @@ gic_config_irq(int irq, enum intr_trigger trig,
(pol != INTR_POLARITY_CONFORM))
goto invalid_args;
- mtx_lock_spin(&arm_gic_sc->mutex);
+ mtx_lock_spin(&sc->mutex);
- reg = gic_d_read_4(GICD_ICFGR(irq >> 4));
+ reg = gic_d_read_4(sc, GICD_ICFGR(irq >> 4));
mask = (reg >> 2*(irq % 16)) & 0x3;
if (pol == INTR_POLARITY_LOW) {
@@ -426,14 +410,14 @@ gic_config_irq(int irq, enum intr_trigger trig,
/* Set mask */
reg = reg & ~(0x3 << 2*(irq % 16));
reg = reg | (mask << 2*(irq % 16));
- gic_d_write_4(GICD_ICFGR(irq >> 4), reg);
+ gic_d_write_4(sc, GICD_ICFGR(irq >> 4), reg);
- mtx_unlock_spin(&arm_gic_sc->mutex);
+ mtx_unlock_spin(&sc->mutex);
return (0);
invalid_args:
- device_printf(arm_gic_sc->dev, "gic_config_irg, invalid parameters\n");
+ device_printf(dev, "gic_config_irg, invalid parameters\n");
return (EINVAL);
}
@@ -441,17 +425,18 @@ invalid_args:
void
pic_ipi_send(cpuset_t cpus, u_int ipi)
{
+ struct arm_gic_softc *sc = arm_gic_sc;
uint32_t val = 0, i;
for (i = 0; i < MAXCPU; i++)
if (CPU_ISSET(i, &cpus))
val |= 1 << (16 + i);
- gic_d_write_4(GICD_SGIR(0), val | ipi);
+ gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
}
int
-pic_ipi_get(int i)
+pic_ipi_read(int i)
{
if (i != -1) {
@@ -463,6 +448,7 @@ pic_ipi_get(int i)
return (0);
return (i);
}
+
return (0x3ff);
}
@@ -472,3 +458,22 @@ pic_ipi_clear(int ipi)
}
#endif
+static device_method_t arm_gic_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, arm_gic_probe),
+ DEVMETHOD(device_attach, arm_gic_attach),
+ { 0, 0 }
+};
+
+static driver_t arm_gic_driver = {
+ "gic",
+ arm_gic_methods,
+ sizeof(struct arm_gic_softc),
+};
+
+static devclass_t arm_gic_devclass;
+
+EARLY_DRIVER_MODULE(gic, simplebus, arm_gic_driver, arm_gic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c
index 955b9f5..1b808ae 100644
--- a/sys/arm/arm/identcpu.c
+++ b/sys/arm/arm/identcpu.c
@@ -457,7 +457,7 @@ identify_arm_cpu(void)
if (arm_cache_level) {
printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
- arm_cache_loc, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
+ arm_cache_loc + 1, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
i = 0;
while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
printf("Cache level %d: \n", i + 1);
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index 83eca07..030407a 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -36,8 +36,11 @@
* Soft interrupt and other generic interrupt functions.
*/
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
@@ -47,10 +50,16 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/conf.h>
+
#include <machine/atomic.h>
#include <machine/intr.h>
#include <machine/cpu.h>
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <machine/fdt.h>
+#endif
+
#define INTRNAME_LEN (MAXCOMLEN + 1)
typedef void (*mask_fn)(void *);
@@ -89,6 +98,36 @@ intr_init(void *unused)
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
+#ifdef FDT
+int
+arm_fdt_map_irq(phandle_t iparent, pcell_t *intr, int icells)
+{
+ fdt_pic_decode_t intr_decode;
+ phandle_t intr_parent;
+ int i, rv, interrupt, trig, pol;
+
+ intr_parent = OF_node_from_xref(iparent);
+ for (i = 0; i < icells; i++)
+ intr[i] = cpu_to_fdt32(intr[i]);
+
+ for (i = 0; fdt_pic_table[i] != NULL; i++) {
+ intr_decode = fdt_pic_table[i];
+ rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol);
+
+ if (rv == 0) {
+ /* This was recognized as our PIC and decoded. */
+ interrupt = FDT_MAP_IRQ(intr_parent, interrupt);
+ return (interrupt);
+ }
+ }
+
+ /* Not in table, so guess */
+ interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0]));
+
+ return (interrupt);
+}
+#endif
+
void
arm_setup_irqhandler(const char *name, driver_filter_t *filt,
void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 341ea4a..f3e75d5 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -378,7 +378,7 @@ cpu_startup(void *dummy)
bufinit();
vm_pager_bufferinit();
- pcb->un_32.pcb32_sp = (u_int)thread0.td_kstack +
+ pcb->pcb_regs.sf_sp = (u_int)thread0.td_kstack +
USPACE_SVC_STACK_TOP;
vector_page_setprot(VM_PROT_READ);
pmap_set_pcb_pagedir(pmap_kernel(), pcb);
@@ -770,14 +770,18 @@ sys_sigreturn(td, uap)
void
makectx(struct trapframe *tf, struct pcb *pcb)
{
- pcb->un_32.pcb32_r8 = tf->tf_r8;
- pcb->un_32.pcb32_r9 = tf->tf_r9;
- pcb->un_32.pcb32_r10 = tf->tf_r10;
- pcb->un_32.pcb32_r11 = tf->tf_r11;
- pcb->un_32.pcb32_r12 = tf->tf_r12;
- pcb->un_32.pcb32_pc = tf->tf_pc;
- pcb->un_32.pcb32_lr = tf->tf_usr_lr;
- pcb->un_32.pcb32_sp = tf->tf_usr_sp;
+ pcb->pcb_regs.sf_r4 = tf->tf_r4;
+ pcb->pcb_regs.sf_r5 = tf->tf_r5;
+ pcb->pcb_regs.sf_r6 = tf->tf_r6;
+ pcb->pcb_regs.sf_r7 = tf->tf_r7;
+ pcb->pcb_regs.sf_r8 = tf->tf_r8;
+ pcb->pcb_regs.sf_r9 = tf->tf_r9;
+ pcb->pcb_regs.sf_r10 = tf->tf_r10;
+ pcb->pcb_regs.sf_r11 = tf->tf_r11;
+ pcb->pcb_regs.sf_r12 = tf->tf_r12;
+ pcb->pcb_regs.sf_pc = tf->tf_pc;
+ pcb->pcb_regs.sf_lr = tf->tf_usr_lr;
+ pcb->pcb_regs.sf_sp = tf->tf_usr_sp;
}
/*
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index a1b29c1..32dce4d 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -266,7 +266,7 @@ ipi_handler(void *arg)
cpu = PCPU_GET(cpuid);
- ipi = pic_ipi_get((int)arg);
+ ipi = pic_ipi_read((int)arg);
while ((ipi != 0x3ff)) {
switch (ipi) {
@@ -329,7 +329,7 @@ ipi_handler(void *arg)
}
pic_ipi_clear(ipi);
- ipi = pic_ipi_get(-1);
+ ipi = pic_ipi_read(-1);
}
return (FILTER_HANDLED);
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index 6678d5d..06f2d6f 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -39,6 +39,8 @@
* and I/O memory address space.
*/
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -60,10 +62,7 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include "opt_platform.h"
-
#ifdef FDT
-#include <dev/fdt/fdt_common.h>
#include <machine/fdt.h>
#include "ofw_bus_if.h"
#endif
@@ -351,28 +350,7 @@ static int
nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
pcell_t *intr)
{
- fdt_pic_decode_t intr_decode;
- phandle_t intr_parent;
- int i, rv, interrupt, trig, pol;
-
- intr_parent = OF_node_from_xref(iparent);
- for (i = 0; i < icells; i++)
- intr[i] = cpu_to_fdt32(intr[i]);
-
- for (i = 0; fdt_pic_table[i] != NULL; i++) {
- intr_decode = fdt_pic_table[i];
- rv = intr_decode(intr_parent, intr, &interrupt, &trig, &pol);
-
- if (rv == 0) {
- /* This was recognized as our PIC and decoded. */
- interrupt = FDT_MAP_IRQ(intr_parent, interrupt);
- return (interrupt);
- }
- }
-
- /* Not in table, so guess */
- interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(intr[0]));
- return (interrupt);
+ return (arm_fdt_map_irq(iparent, intr, icells));
}
#endif
diff --git a/sys/arm/arm/stack_machdep.c b/sys/arm/arm/stack_machdep.c
index f1708f5..9c984a9 100644
--- a/sys/arm/arm/stack_machdep.c
+++ b/sys/arm/arm/stack_machdep.c
@@ -76,7 +76,7 @@ stack_save_td(struct stack *st, struct thread *td)
* as it doesn't have a frame pointer, however it's value is not used
* when building for EABI.
*/
- frame = (u_int32_t *)td->td_pcb->un_32.pcb32_r11;
+ frame = (u_int32_t *)td->td_pcb->pcb_regs.sf_r11;
stack_zero(st);
stack_capture(st, frame);
}
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index 610d575..e9d6f61 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -116,6 +116,14 @@ __FBSDID("$FreeBSD$");
.Lblocked_lock:
.word _C_LABEL(blocked_lock)
+/*
+ * cpu_throw(oldtd, newtd)
+ *
+ * Remove current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ */
ENTRY(cpu_throw)
mov r5, r1
@@ -144,7 +152,6 @@ ENTRY(cpu_throw)
* r0 = Pointer to L1 slot for vector_page (or NULL)
* r1 = lwp0's DACR
* r5 = lwp0
- * r6 = exit func
* r7 = lwp0's PCB
* r9 = cpufuncs
*/
@@ -181,25 +188,11 @@ ENTRY(cpu_throw)
mov lr, pc
ldr pc, [r9, #CF_CONTEXT_SWITCH]
- /* Restore all the save registers */
-#ifndef _ARM_ARCH_5E
- add r1, r7, #PCB_R8
- ldmia r1, {r8-r13}
-#else
- ldr r8, [r7, #(PCB_R8)]
- ldr r9, [r7, #(PCB_R9)]
- ldr r10, [r7, #(PCB_R10)]
- ldr r11, [r7, #(PCB_R11)]
- ldr r12, [r7, #(PCB_R12)]
- ldr r13, [r7, #(PCB_SP)]
-#endif
-
GET_PCPU(r6, r4)
/* Hook in a new pcb */
str r7, [r6, #PC_CURPCB]
/* We have a new curthread now so make a note it */
- add r6, r6, #PC_CURTHREAD
- str r5, [r6]
+ str r5, [r6, #PC_CURTHREAD]
#ifndef ARM_TP_ADDRESS
mcr p15, 0, r5, c13, c0, 4
#endif
@@ -215,22 +208,31 @@ ENTRY(cpu_throw)
#else
mcr p15, 0, r6, c13, c0, 3
#endif
-
- add sp, sp, #4;
- ldmfd sp!, {r4-r7, pc}
+ /* Restore all the saved registers and exit */
+ add r3, r7, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
END(cpu_throw)
+/*
+ * cpu_switch(oldtd, newtd, lock)
+ *
+ * Save the current thread state, then select the next thread to run
+ * and load its state.
+ * r0 = oldtd
+ * r1 = newtd
+ * r2 = lock (new lock for old thread)
+ */
ENTRY(cpu_switch)
- stmfd sp!, {r4-r7, lr}
- sub sp, sp, #4;
-#ifdef __ARM_EABI__
- .save {r4-r7, lr}
- .pad #4
-#endif
+ /* Interrupts are disabled. */
+ /* Save all the registers in the old thread's pcb. */
+ ldr r3, [r0, #(TD_PCB)]
+
+ /* Restore all the saved registers and exit */
+ add r3, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
mov r6, r2 /* Save the mutex */
-.Lswitch_resume:
/* rem: r0 = old lwp */
/* rem: interrupts are disabled */
@@ -246,30 +248,12 @@ ENTRY(cpu_switch)
ldr r2, [r1, #TD_PCB]
str r2, [r7, #PC_CURPCB]
- /* rem: r1 = new process */
- /* rem: interrupts are enabled */
-
/* Stage two : Save old context */
/* Get the user structure for the old thread. */
ldr r2, [r0, #(TD_PCB)]
mov r4, r0 /* Save the old thread. */
- /* Save all the registers in the old thread's pcb */
-#ifndef _ARM_ARCH_5E
- add r7, r2, #(PCB_R8)
- stmia r7, {r8-r13}
-#else
- strd r8, [r2, #(PCB_R8)]
- strd r10, [r2, #(PCB_R10)]
- strd r12, [r2, #(PCB_R12)]
-#endif
- str pc, [r2, #(PCB_PC)]
-
- /*
- * NOTE: We can now use r8-r13 until it is time to restore
- * them for the new process.
- */
#ifdef ARM_TP_ADDRESS
/* Store the old tp */
ldr r3, =ARM_TP_ADDRESS
@@ -318,7 +302,6 @@ ENTRY(cpu_switch)
/* rem: r2 = old PCB */
/* rem: r9 = new PCB */
- /* rem: interrupts are enabled */
ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */
mov r2, #DOMAIN_CLIENT
@@ -336,7 +319,6 @@ ENTRY(cpu_switch)
mrc p15, 0, r10, c2, c0, 0 /* r10 = old L1 */
ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
-
teq r10, r11 /* Same L1? */
cmpeq r0, r5 /* Same DACR? */
beq .Lcs_context_switched /* yes! */
@@ -426,54 +408,18 @@ ENTRY(cpu_switch)
/* rem: r9 = new PCB */
- /* Restore all the save registers */
-#ifndef _ARM_ARCH_5E
- add r7, r9, #PCB_R8
- ldmia r7, {r8-r13}
- sub r7, r7, #PCB_R8 /* restore PCB pointer */
-#else
- mov r7, r9
- ldr r8, [r7, #(PCB_R8)]
- ldr r9, [r7, #(PCB_R9)]
- ldr r10, [r7, #(PCB_R10)]
- ldr r11, [r7, #(PCB_R11)]
- ldr r12, [r7, #(PCB_R12)]
- ldr r13, [r7, #(PCB_SP)]
-#endif
-
- /* rem: r5 = new lwp's proc */
- /* rem: r6 = lock */
- /* rem: r7 = new PCB */
-
-.Lswitch_return:
-
- /*
- * Pull the registers that got pushed when either savectx() or
- * cpu_switch() was called and return.
- */
- add sp, sp, #4;
- ldmfd sp!, {r4-r7, pc}
-#ifdef DIAGNOSTIC
-.Lswitch_bogons:
- adr r0, .Lswitch_panic_str
- bl _C_LABEL(panic)
-1: nop
- b 1b
-
-.Lswitch_panic_str:
- .asciz "cpu_switch: sched_qs empty with non-zero sched_whichqs!\n"
-#endif
+ /* Restore all the saved registers and exit */
+ add r3, r9, #PCB_R4
+ ldmia r3, {r4-r12, sp, pc}
END(cpu_switch)
ENTRY(savectx)
- stmfd sp!, {r4-r7, lr}
+ stmfd sp!, {lr}
sub sp, sp, #4
- /*
- * r0 = pcb
- */
- /* Store all the registers in the process's pcb */
- add r2, r0, #(PCB_R8)
- stmia r2, {r8-r13}
+
+ /* Store all the registers in the thread's pcb */
+ add r3, r0, #(PCB_R4)
+ stmia r3, {r4-r12, sp, lr, pc}
#ifdef VFP
fmrx r2, fpexc /* If the VFP is enabled */
tst r2, #(VFPEXC_EN) /* the current thread has */
@@ -482,7 +428,7 @@ ENTRY(savectx)
blne _C_LABEL(vfp_store) /* and disable the VFP. */
#endif
add sp, sp, #4;
- ldmfd sp!, {r4-r7, pc}
+ ldmfd sp!, {pc}
END(savectx)
ENTRY(fork_trampoline)
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index ec14feb..081cfaa 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -127,6 +127,7 @@ static int dab_align(struct trapframe *, u_int, u_int, struct thread *,
struct ksig *);
static int dab_buserr(struct trapframe *, u_int, u_int, struct thread *,
struct ksig *);
+static void prefetch_abort_handler(struct trapframe *);
static const struct data_abort data_aborts[] = {
{dab_fatal, "Vector Exception"},
@@ -171,7 +172,7 @@ call_trapsignal(struct thread *td, int sig, u_long code)
}
void
-data_abort_handler(struct trapframe *tf)
+abort_handler(struct trapframe *tf, int type)
{
struct vm_map *map;
struct pcb *pcb;
@@ -184,6 +185,8 @@ data_abort_handler(struct trapframe *tf)
struct ksig ksig;
struct proc *p;
+ if (type == 1)
+ return (prefetch_abort_handler(tf));
/* Grab FAR/FSR before enabling interrupts */
far = cpu_faultaddress();
@@ -545,7 +548,7 @@ dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
* If the current trapframe is at the top of the kernel stack,
* the fault _must_ have come from user mode.
*/
- if (tf != ((struct trapframe *)pcb->un_32.pcb32_sp) - 1) {
+ if (tf != ((struct trapframe *)pcb->pcb_regs.sf_sp) - 1) {
/*
* Kernel mode. We're either about to die a
* spectacular death, or pcb_onfault will come
@@ -605,7 +608,7 @@ dab_buserr(struct trapframe *tf, u_int fsr, u_int far, struct thread *td,
* does no have read permission so send it a signal.
* Otherwise fault the page in and try again.
*/
-void
+static void
prefetch_abort_handler(struct trapframe *tf)
{
struct thread *td;
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 7758a22..42587f5 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -79,7 +79,7 @@ __FBSDID("$FreeBSD$");
* struct switchframe and trapframe must both be a multiple of 8
* for correct stack alignment.
*/
-CTASSERT(sizeof(struct switchframe) == 24);
+CTASSERT(sizeof(struct switchframe) == 48);
CTASSERT(sizeof(struct trapframe) == 80);
/*
@@ -93,43 +93,55 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
{
struct pcb *pcb2;
struct trapframe *tf;
- struct switchframe *sf;
struct mdproc *mdp2;
if ((flags & RFPROC) == 0)
return;
- pcb2 = (struct pcb *)(td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
+
+ /* Point the pcb to the top of the stack */
+ pcb2 = (struct pcb *)
+ (td2->td_kstack + td2->td_kstack_pages * PAGE_SIZE) - 1;
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
#endif
#endif
td2->td_pcb = pcb2;
+
+ /* Clone td1's pcb */
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
+
+ /* Point to mdproc and then copy over td1's contents */
mdp2 = &p2->p_md;
bcopy(&td1->td_proc->p_md, mdp2, sizeof(*mdp2));
- pcb2->un_32.pcb32_sp = td2->td_kstack +
- USPACE_SVC_STACK_TOP - sizeof(*pcb2);
+
+ /* Point the frame to the stack in front of pcb and copy td1's frame */
+ td2->td_frame = (struct trapframe *)pcb2 - 1;
+ *td2->td_frame = *td1->td_frame;
+
+ /*
+ * Create a new fresh stack for the new process.
+ * Copy the trap frame for the return to user mode as if from a
+ * syscall. This copies most of the user mode register values.
+ */
+ pmap_set_pcb_pagedir(vmspace_pmap(p2->p_vmspace), pcb2);
+ pcb2->pcb_regs.sf_r4 = (register_t)fork_return;
+ pcb2->pcb_regs.sf_r5 = (register_t)td2;
+ pcb2->pcb_regs.sf_lr = (register_t)fork_trampoline;
+ pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
+
pcb2->pcb_vfpcpu = -1;
pcb2->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
- pmap_activate(td2);
- td2->td_frame = tf = (struct trapframe *)STACKALIGN(
- pcb2->un_32.pcb32_sp - sizeof(struct trapframe));
- *tf = *td1->td_frame;
- sf = (struct switchframe *)tf - 1;
- sf->sf_r4 = (u_int)fork_return;
- sf->sf_r5 = (u_int)td2;
- sf->sf_pc = (u_int)fork_trampoline;
+
+ tf = td2->td_frame;
tf->tf_spsr &= ~PSR_C;
tf->tf_r0 = 0;
tf->tf_r1 = 0;
- pcb2->un_32.pcb32_sp = (u_int)sf;
- KASSERT((pcb2->un_32.pcb32_sp & 7) == 0,
- ("cpu_fork: Incorrect stack alignment"));
+
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
- td2->td_md.md_saved_cspr = 0;
+ td2->td_md.md_saved_cspr = PSR_SVC32_MODE;;
#ifdef ARM_TP_ADDRESS
td2->td_md.md_tp = *(register_t *)ARM_TP_ADDRESS;
#else
@@ -218,25 +230,21 @@ cpu_set_syscall_retval(struct thread *td, int error)
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{
- struct trapframe *tf;
- struct switchframe *sf;
bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
- tf = td->td_frame;
- sf = (struct switchframe *)tf - 1;
- sf->sf_r4 = (u_int)fork_return;
- sf->sf_r5 = (u_int)td;
- sf->sf_pc = (u_int)fork_trampoline;
- tf->tf_spsr &= ~PSR_C;
- tf->tf_r0 = 0;
- td->td_pcb->un_32.pcb32_sp = (u_int)sf;
- KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
- ("cpu_set_upcall: Incorrect stack alignment"));
+
+ td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return;
+ td->td_pcb->pcb_regs.sf_r5 = (register_t)td;
+ td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline;
+ td->td_pcb->pcb_regs.sf_sp = STACKALIGN(td->td_frame);
+
+ td->td_frame->tf_spsr &= ~PSR_C;
+ td->td_frame->tf_r0 = 0;
/* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
- td->td_md.md_saved_cspr = 0;
+ td->td_md.md_saved_cspr = PSR_SVC32_MODE;
}
/*
@@ -250,8 +258,7 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
{
struct trapframe *tf = td->td_frame;
- tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size
- - sizeof(struct trapframe));
+ tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size);
tf->tf_pc = (int)entry;
tf->tf_r0 = (int)arg;
tf->tf_spsr = PSR_USR32_MODE;
@@ -289,9 +296,8 @@ cpu_thread_alloc(struct thread *td)
* placed into the stack pointer which must be 8 byte aligned in
* the ARM EABI.
*/
- td->td_frame = (struct trapframe *)STACKALIGN((u_int)td->td_kstack +
- USPACE_SVC_STACK_TOP - sizeof(struct pcb) -
- sizeof(struct trapframe));
+ td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb) - 1;
+
#ifdef __XSCALE__
#ifndef CPU_XSCALE_CORE3
pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
@@ -318,16 +324,8 @@ cpu_thread_clean(struct thread *td)
void
cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
{
- struct switchframe *sf;
- struct trapframe *tf;
-
- tf = td->td_frame;
- sf = (struct switchframe *)tf - 1;
- sf->sf_r4 = (u_int)func;
- sf->sf_r5 = (u_int)arg;
- td->td_pcb->un_32.pcb32_sp = (u_int)sf;
- KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
- ("cpu_set_fork_handler: Incorrect stack alignment"));
+ td->td_pcb->pcb_regs.sf_r4 = (register_t)func; /* function */
+ td->td_pcb->pcb_regs.sf_r5 = (register_t)arg; /* first arg */
}
/*
diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c
index 0f6b79b..293a352 100644
--- a/sys/arm/at91/at91_machdep.c
+++ b/sys/arm/at91/at91_machdep.c
@@ -117,8 +117,6 @@ extern struct bus_space at91_bs_tag;
struct pv_addr kernel_pt_table[NUM_KERNEL_PTS];
-extern uint32_t at91_master_clock;
-
/* Static device mappings. */
const struct arm_devmap_entry at91_devmap[] = {
/*
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
new file mode 100644
index 0000000..686e80c
--- /dev/null
+++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
@@ -0,0 +1,1818 @@
+/*-
+ * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama@peach.ne.jp>
+ * 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sema.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
+#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+
+#include "cpufreq_if.h"
+#include "mbox_if.h"
+
+#ifdef DEBUG
+#define DPRINTF(fmt, ...) do { \
+ printf("%s:%u: ", __func__, __LINE__); \
+ printf(fmt, ##__VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#define HZ2MHZ(freq) ((freq) / (1000 * 1000))
+#define MHZ2HZ(freq) ((freq) * (1000 * 1000))
+#define OFFSET2MVOLT(val) (1200 + ((val) * 25))
+#define MVOLT2OFFSET(val) (((val) - 1200) / 25)
+#define RAW2K(temp) (((temp) + 273150) / 1000)
+#define K2RAW(temp) (((temp) * 1000) - 273150)
+
+#define DEFAULT_ARM_FREQUENCY 700
+#define DEFAULT_CORE_FREQUENCY 250
+#define DEFAULT_SDRAM_FREQUENCY 400
+#define DEFAULT_LOWEST_FREQ 300
+#define TRANSITION_LATENCY 1000
+#define MIN_OVER_VOLTAGE -16
+#define MAX_OVER_VOLTAGE 6
+#define MSG_ERROR -999999999
+#define MHZSTEP 100
+#define HZSTEP (MHZ2HZ(MHZSTEP))
+
+#define VC_LOCK(sc) do { \
+ sema_wait(&vc_sema); \
+ } while (0)
+#define VC_UNLOCK(sc) do { \
+ sema_post(&vc_sema); \
+ } while (0)
+
+/* ARM->VC mailbox property semaphore */
+static struct sema vc_sema;
+
+static struct sysctl_ctx_list bcm2835_sysctl_ctx;
+
+struct bcm2835_cpufreq_softc {
+ device_t dev;
+ int arm_max_freq;
+ int arm_min_freq;
+ int core_max_freq;
+ int core_min_freq;
+ int sdram_max_freq;
+ int sdram_min_freq;
+ int max_voltage_core;
+ int min_voltage_core;
+
+ /* the values written in mbox */
+ int voltage_core;
+ int voltage_sdram;
+ int voltage_sdram_c;
+ int voltage_sdram_i;
+ int voltage_sdram_p;
+ int turbo_mode;
+
+ /* mbox buffer (physical address) */
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ bus_size_t dma_size;
+ void *dma_buf;
+ bus_addr_t dma_phys;
+
+ /* initial hook for waiting mbox intr */
+ struct intr_config_hook init_hook;
+};
+
+static int cpufreq_verbose = 0;
+TUNABLE_INT("hw.bcm2835.cpufreq.verbose", &cpufreq_verbose);
+static int cpufreq_lowest_freq = DEFAULT_LOWEST_FREQ;
+TUNABLE_INT("hw.bcm2835.cpufreq.lowest_freq", &cpufreq_lowest_freq);
+
+#ifdef PROP_DEBUG
+static void
+bcm2835_dump(const void *data, int len)
+{
+ const uint8_t *p = (const uint8_t*)data;
+ int i;
+
+ printf("dump @ %p:\n", data);
+ for (i = 0; i < len; i++) {
+ printf("%2.2x ", p[i]);
+ if ((i % 4) == 3)
+ printf(" ");
+ if ((i % 16) == 15)
+ printf("\n");
+ }
+ printf("\n");
+}
+#endif
+
+static int
+bcm2835_mbox_call_prop(struct bcm2835_cpufreq_softc *sc)
+{
+ struct bcm2835_mbox_hdr *msg = (struct bcm2835_mbox_hdr *)sc->dma_buf;
+ struct bcm2835_mbox_tag_hdr *tag, *last;
+ uint8_t *up;
+ device_t mbox;
+ size_t hdr_size;
+ int idx;
+ int err;
+
+ /*
+ * For multiple calls, locking is not here. The caller must have
+ * VC semaphore.
+ */
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL) {
+ device_printf(sc->dev, "can't find mbox\n");
+ return (-1);
+ }
+
+ /* go mailbox property */
+#ifdef PROP_DEBUG
+ bcm2835_dump(msg, 64);
+#endif
+ bus_dmamap_sync(sc->dma_tag, sc->dma_map,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)sc->dma_phys);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &err);
+ bus_dmamap_sync(sc->dma_tag, sc->dma_map, BUS_DMASYNC_POSTREAD);
+#ifdef PROP_DEBUG
+ bcm2835_dump(msg, 64);
+#endif
+
+ /* check response code */
+ if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) {
+ device_printf(sc->dev, "mbox response error\n");
+ return (-1);
+ }
+
+ /* tag = first tag */
+ up = (uint8_t *)msg;
+ hdr_size = sizeof(struct bcm2835_mbox_hdr);
+ tag = (struct bcm2835_mbox_tag_hdr *)(up + hdr_size);
+ /* last = end of buffer specified by header */
+ last = (struct bcm2835_mbox_tag_hdr *)(up + msg->buf_size);
+
+ /* loop unitl end tag (=0x0) */
+ hdr_size = sizeof(struct bcm2835_mbox_tag_hdr);
+ for (idx = 0; tag->tag != 0; idx++) {
+ if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) {
+ device_printf(sc->dev, "tag%d response error\n", idx);
+ return (-1);
+ }
+ /* clear response bit */
+ tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+
+ /* get next tag */
+ up = (uint8_t *)tag;
+ tag = (struct bcm2835_mbox_tag_hdr *)(up + hdr_size +
+ tag->val_buf_size);
+
+ /* check buffer size of header */
+ if (tag > last) {
+ device_printf(sc->dev, "mbox buffer size error\n");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_clock_rate *msg;
+ int rate;
+ int err;
+
+ /*
+ * Get clock rate
+ * Tag: 0x00030002
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_clock_rate *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.clock_id = clock_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg->body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_max_clock_rate *msg;
+ int rate;
+ int err;
+
+ /*
+ * Get max clock rate
+ * Tag: 0x00030004
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_max_clock_rate *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.clock_id = clock_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get max clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg->body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id)
+{
+ struct msg_get_min_clock_rate *msg;
+ int rate;
+ int err;
+
+ /*
+ * Get min clock rate
+ * Tag: 0x00030007
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: clock id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_min_clock_rate *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.clock_id = clock_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get min clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* result (Hz) */
+ rate = (int)msg->body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc,
+ uint32_t clock_id, uint32_t rate_hz)
+{
+ struct msg_set_clock_rate *msg;
+ int rate;
+ int err;
+
+ /*
+ * Set clock rate
+ * Tag: 0x00038002
+ * Request:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: clock id
+ * u32: rate (in Hz)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_set_clock_rate *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.clock_id = clock_id;
+ msg->body.req.rate_hz = rate_hz;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't set clock rate (id=%u)\n",
+ clock_id);
+ return (MSG_ERROR);
+ }
+
+ /* workaround for core clock */
+ if (clock_id == BCM2835_MBOX_CLOCK_ID_CORE) {
+ /* for safety (may change voltage without changing clock) */
+ DELAY(TRANSITION_LATENCY);
+
+ /*
+ * XXX: the core clock is unable to change at once,
+ * to change certainly, write it twice now.
+ */
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.clock_id = clock_id;
+ msg->body.req.rate_hz = rate_hz;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev,
+ "can't set clock rate (id=%u)\n", clock_id);
+ return (MSG_ERROR);
+ }
+ }
+
+ /* result (Hz) */
+ rate = (int)msg->body.resp.rate_hz;
+ DPRINTF("clock = %d(Hz)\n", rate);
+ return (rate);
+}
+
+static int
+bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc)
+{
+ struct msg_get_turbo *msg;
+ int level;
+ int err;
+
+ /*
+ * Get turbo
+ * Tag: 0x00030009
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_turbo *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_TURBO;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.id = 0;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get turbo\n");
+ return (MSG_ERROR);
+ }
+
+ /* result 0=non-turbo, 1=turbo */
+ level = (int)msg->body.resp.level;
+ DPRINTF("level = %d\n", level);
+ return (level);
+}
+
+static int
+bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level)
+{
+ struct msg_set_turbo *msg;
+ int value;
+ int err;
+
+ /*
+ * Set turbo
+ * Tag: 0x00038009
+ * Request:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: id
+ * u32: level
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_set_turbo *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* replace unknown value to OFF */
+ if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF)
+ level = BCM2835_MBOX_TURBO_OFF;
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_SET_TURBO;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.id = 0;
+ msg->body.req.level = level;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't set turbo\n");
+ return (MSG_ERROR);
+ }
+
+ /* result 0=non-turbo, 1=turbo */
+ value = (int)msg->body.resp.level;
+ DPRINTF("level = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_voltage *msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030003
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_voltage *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_VOLTAGE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.voltage_id = voltage_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg->body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_max_voltage *msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030005
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_max_voltage *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_VOLTAGE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.voltage_id = voltage_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get max voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg->body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+static int
+bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id)
+{
+ struct msg_get_min_voltage *msg;
+ int value;
+ int err;
+
+ /*
+ * Get voltage
+ * Tag: 0x00030008
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_min_voltage *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_VOLTAGE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.voltage_id = voltage_id;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get min voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg->body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc,
+ uint32_t voltage_id, int32_t value)
+{
+ struct msg_set_voltage *msg;
+ int err;
+
+ /*
+ * Set voltage
+ * Tag: 0x00038003
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: voltage id
+ * u32: value (offset from 1.2V in units of 0.025V)
+ */
+
+ /*
+ * over_voltage:
+ * 0 (1.2 V). Values above 6 are only allowed when force_turbo or
+ * current_limit_override are specified (which set the warranty bit).
+ */
+ if (value > MAX_OVER_VOLTAGE || value < MIN_OVER_VOLTAGE) {
+ /* currently not supported */
+ device_printf(sc->dev, "not supported voltage: %d\n", value);
+ return (MSG_ERROR);
+ }
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_set_voltage *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_SET_VOLTAGE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.voltage_id = voltage_id;
+ msg->body.req.value = (uint32_t)value;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't set voltage\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (offset from 1.2V) */
+ value = (int)msg->body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+static int
+bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc)
+{
+ struct msg_get_temperature *msg;
+ int value;
+ int err;
+
+ /*
+ * Get temperature
+ * Tag: 0x00030006
+ * Request:
+ * Length: 4
+ * Value:
+ * u32: temperature id
+ * Response:
+ * Length: 8
+ * Value:
+ * u32: temperature id
+ * u32: value
+ */
+
+ /* using DMA buffer for VC */
+ msg = (struct msg_get_temperature *)sc->dma_buf;
+ if (sizeof(*msg) > sc->dma_size) {
+ device_printf(sc->dev, "DMA size overflow (%zu>%lu)\n",
+ sizeof(*msg), sc->dma_size);
+ return (MSG_ERROR);
+ }
+
+ /* setup single tag buffer */
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ msg->tag_hdr.tag = BCM2835_MBOX_TAG_GET_TEMPERATURE;
+ msg->tag_hdr.val_buf_size = sizeof(msg->body);
+ msg->tag_hdr.val_len = sizeof(msg->body.req);
+ msg->body.req.temperature_id = 0;
+ msg->end_tag = 0;
+
+ /* call mailbox property */
+ err = bcm2835_mbox_call_prop(sc);
+ if (err) {
+ device_printf(sc->dev, "can't get temperature\n");
+ return (MSG_ERROR);
+ }
+
+ /* result (temperature of degree C) */
+ value = (int)msg->body.resp.value;
+ DPRINTF("value = %d\n", value);
+ return (value);
+}
+
+
+
+static int
+sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ val);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set clock arm_freq error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set clock core_freq error\n");
+ return (EIO);
+ }
+ VC_UNLOCK(sc);
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM,
+ val);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set clock sdram_freq error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_turbo(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > 0)
+ sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
+ else
+ sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set turbo error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_core = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE,
+ sc->voltage_core);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage core error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_c = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
+ sc->voltage_sdram_c);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_c error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_i = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
+ sc->voltage_sdram_i);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_i error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram_p = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
+ sc->voltage_sdram_p);
+ VC_UNLOCK(sc);
+ if (err == MSG_ERROR) {
+ device_printf(sc->dev, "set voltage sdram_p error\n");
+ return (EIO);
+ }
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* multiple write only */
+ if (!req->newptr)
+ return (EINVAL);
+ val = 0;
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err)
+ return (err);
+
+ /* write request */
+ if (val > MAX_OVER_VOLTAGE || val < MIN_OVER_VOLTAGE)
+ return (EINVAL);
+ sc->voltage_sdram = val;
+
+ VC_LOCK(sc);
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_c error\n");
+ return (EIO);
+ }
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_i error\n");
+ return (EIO);
+ }
+ err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P,
+ val);
+ if (err == MSG_ERROR) {
+ VC_UNLOCK(sc);
+ device_printf(sc->dev, "set voltage sdram_p error\n");
+ return (EIO);
+ }
+ VC_UNLOCK(sc);
+ DELAY(TRANSITION_LATENCY);
+
+ return (0);
+}
+
+static int
+sysctl_bcm2835_cpufreq_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_temperature(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ return (EINVAL);
+}
+
+static int
+sysctl_bcm2835_devcpu_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct bcm2835_cpufreq_softc *sc = arg1;
+ int val;
+ int err;
+
+ /* get realtime value */
+ VC_LOCK(sc);
+ val = bcm2835_cpufreq_get_temperature(sc);
+ VC_UNLOCK(sc);
+ if (val == MSG_ERROR)
+ return (EIO);
+
+ /* 1/1000 celsius (raw) to 1/10 kelvin */
+ val = RAW2K(val) * 10;
+
+ err = sysctl_handle_int(oidp, &val, 0, req);
+ if (err || !req->newptr) /* error || read request */
+ return (err);
+
+ /* write request */
+ return (EINVAL);
+}
+
+
+static void
+bcm2835_cpufreq_init(void *arg)
+{
+ struct bcm2835_cpufreq_softc *sc = arg;
+ struct sysctl_ctx_list *ctx;
+ device_t cpu;
+ int arm_freq, core_freq, sdram_freq;
+ int arm_max_freq, arm_min_freq, core_max_freq, core_min_freq;
+ int sdram_max_freq, sdram_min_freq;
+ int voltage_core, voltage_sdram_c, voltage_sdram_i, voltage_sdram_p;
+ int max_voltage_core, min_voltage_core;
+ int max_voltage_sdram_c, min_voltage_sdram_c;
+ int max_voltage_sdram_i, min_voltage_sdram_i;
+ int max_voltage_sdram_p, min_voltage_sdram_p;
+ int turbo, temperature;
+
+ VC_LOCK(sc);
+
+ /* current clock */
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ core_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ sdram_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+
+ /* max/min clock */
+ arm_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ arm_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ core_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ core_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ sdram_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+ sdram_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM);
+
+ /* turbo mode */
+ turbo = bcm2835_cpufreq_get_turbo(sc);
+ if (turbo > 0)
+ sc->turbo_mode = BCM2835_MBOX_TURBO_ON;
+ else
+ sc->turbo_mode = BCM2835_MBOX_TURBO_OFF;
+
+ /* voltage */
+ voltage_core = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ voltage_sdram_c = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ voltage_sdram_i = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ voltage_sdram_p = bcm2835_cpufreq_get_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+
+ /* current values (offset from 1.2V) */
+ sc->voltage_core = voltage_core;
+ sc->voltage_sdram = voltage_sdram_c;
+ sc->voltage_sdram_c = voltage_sdram_c;
+ sc->voltage_sdram_i = voltage_sdram_i;
+ sc->voltage_sdram_p = voltage_sdram_p;
+
+ /* max/min voltage */
+ max_voltage_core = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ min_voltage_core = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE);
+ max_voltage_sdram_c = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ max_voltage_sdram_i = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ max_voltage_sdram_p = bcm2835_cpufreq_get_max_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+ min_voltage_sdram_c = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_C);
+ min_voltage_sdram_i = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_I);
+ min_voltage_sdram_p = bcm2835_cpufreq_get_min_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_SDRAM_P);
+
+ /* temperature */
+ temperature = bcm2835_cpufreq_get_temperature(sc);
+
+ /* show result */
+ if (cpufreq_verbose || bootverbose) {
+ device_printf(sc->dev, "Boot settings:\n");
+ device_printf(sc->dev,
+ "current ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
+ HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
+ (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
+
+ device_printf(sc->dev,
+ "max/min ARM %d/%dMHz, Core %d/%dMHz, SDRAM %d/%dMHz\n",
+ HZ2MHZ(arm_max_freq), HZ2MHZ(arm_min_freq),
+ HZ2MHZ(core_max_freq), HZ2MHZ(core_min_freq),
+ HZ2MHZ(sdram_max_freq), HZ2MHZ(sdram_min_freq));
+
+ device_printf(sc->dev,
+ "current Core %dmV, SDRAM_C %dmV, SDRAM_I %dmV, "
+ "SDRAM_P %dmV\n",
+ OFFSET2MVOLT(voltage_core), OFFSET2MVOLT(voltage_sdram_c),
+ OFFSET2MVOLT(voltage_sdram_i),
+ OFFSET2MVOLT(voltage_sdram_p));
+
+ device_printf(sc->dev,
+ "max/min Core %d/%dmV, SDRAM_C %d/%dmV, SDRAM_I %d/%dmV, "
+ "SDRAM_P %d/%dmV\n",
+ OFFSET2MVOLT(max_voltage_core),
+ OFFSET2MVOLT(min_voltage_core),
+ OFFSET2MVOLT(max_voltage_sdram_c),
+ OFFSET2MVOLT(min_voltage_sdram_c),
+ OFFSET2MVOLT(max_voltage_sdram_i),
+ OFFSET2MVOLT(min_voltage_sdram_i),
+ OFFSET2MVOLT(max_voltage_sdram_p),
+ OFFSET2MVOLT(min_voltage_sdram_p));
+
+ device_printf(sc->dev,
+ "Temperature %d.%dC\n", (temperature / 1000),
+ (temperature % 1000) / 100);
+ } else { /* !cpufreq_verbose && !bootverbose */
+ device_printf(sc->dev,
+ "ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n",
+ HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq),
+ (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF");
+ }
+
+ /* keep in softc (MHz/mV) */
+ sc->arm_max_freq = HZ2MHZ(arm_max_freq);
+ sc->arm_min_freq = HZ2MHZ(arm_min_freq);
+ sc->core_max_freq = HZ2MHZ(core_max_freq);
+ sc->core_min_freq = HZ2MHZ(core_min_freq);
+ sc->sdram_max_freq = HZ2MHZ(sdram_max_freq);
+ sc->sdram_min_freq = HZ2MHZ(sdram_min_freq);
+ sc->max_voltage_core = OFFSET2MVOLT(max_voltage_core);
+ sc->min_voltage_core = OFFSET2MVOLT(min_voltage_core);
+
+ /* if turbo is on, set to max values */
+ if (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) {
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ arm_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ core_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_max_freq);
+ DELAY(TRANSITION_LATENCY);
+ } else {
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM,
+ arm_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE,
+ core_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_min_freq);
+ DELAY(TRANSITION_LATENCY);
+ }
+
+ VC_UNLOCK(sc);
+
+ /* add human readable temperature to dev.cpu node */
+ cpu = device_get_parent(sc->dev);
+ if (cpu != NULL) {
+ ctx = device_get_sysctl_ctx(cpu);
+ SYSCTL_ADD_PROC(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)), OID_AUTO,
+ "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ sysctl_bcm2835_devcpu_temperature, "IK",
+ "Current SoC temperature");
+ }
+
+ /* release this hook (continue boot) */
+ config_intrhook_disestablish(&sc->init_hook);
+}
+
+static void
+bcm2835_cpufreq_identify(driver_t *driver, device_t parent)
+{
+
+ DPRINTF("driver=%p, parent=%p\n", driver, parent);
+ if (device_find_child(parent, "bcm2835_cpufreq", -1) != NULL)
+ return;
+ if (BUS_ADD_CHILD(parent, 0, "bcm2835_cpufreq", -1) == NULL)
+ device_printf(parent, "add child failed\n");
+}
+
+static int
+bcm2835_cpufreq_probe(device_t dev)
+{
+
+ device_set_desc(dev, "CPU Frequency Control");
+ return (0);
+}
+
+static void
+bcm2835_cpufreq_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
+{
+ bus_addr_t *addr;
+
+ if (err)
+ return;
+ addr = (bus_addr_t *)arg;
+ *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
+}
+
+static int
+bcm2835_cpufreq_attach(device_t dev)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ struct sysctl_oid *oid;
+ int err;
+
+ /* set self dev */
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* initial values */
+ sc->arm_max_freq = -1;
+ sc->arm_min_freq = -1;
+ sc->core_max_freq = -1;
+ sc->core_min_freq = -1;
+ sc->sdram_max_freq = -1;
+ sc->sdram_min_freq = -1;
+ sc->max_voltage_core = 0;
+ sc->min_voltage_core = 0;
+
+ /* create VC mbox buffer */
+ sc->dma_size = PAGE_SIZE;
+ err = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev),
+ PAGE_SIZE, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ sc->dma_size, 1, /* maxsize, nsegments */
+ sc->dma_size, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->dma_tag);
+ if (err) {
+ device_printf(dev, "can't create DMA tag\n");
+ return (ENXIO);
+ }
+
+ err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->dma_buf, 0,
+ &sc->dma_map);
+ if (err) {
+ bus_dma_tag_destroy(sc->dma_tag);
+ device_printf(dev, "can't allocate dmamem\n");
+ return (ENXIO);
+ }
+
+ err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->dma_buf,
+ sc->dma_size, bcm2835_cpufreq_cb, &sc->dma_phys, 0);
+ if (err) {
+ bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map);
+ bus_dma_tag_destroy(sc->dma_tag);
+ device_printf(dev, "can't load DMA map\n");
+ return (ENXIO);
+ }
+ /* OK, ready to use VC buffer */
+
+ /* setup sysctl at first device */
+ if (device_get_unit(dev) == 0) {
+ sysctl_ctx_init(&bcm2835_sysctl_ctx);
+ /* create node for hw.cpufreq */
+ oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
+ CTLFLAG_RD, NULL, "");
+
+ /* Frequency (Hz) */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_arm_freq, "IU",
+ "ARM frequency (Hz)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_core_freq, "IU",
+ "Core frequency (Hz)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_sdram_freq, "IU",
+ "SDRAM frequency (Hz)");
+
+ /* Turbo state */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_turbo, "IU",
+ "Disables dynamic clocking");
+
+ /* Voltage (offset from 1.2V in units of 0.025V) */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ sysctl_bcm2835_cpufreq_voltage_core, "I",
+ "ARM/GPU core voltage"
+ "(offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
+ "SDRAM voltage (offset from 1.2V in units of 0.025V)");
+
+ /* Voltage individual SDRAM */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
+ "SDRAM controller voltage"
+ "(offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
+ "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc,
+ 0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
+ "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");
+
+ /* Temperature */
+ SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
+ sysctl_bcm2835_cpufreq_temperature, "I",
+ "SoC temperature (thousandths of a degree C)");
+ }
+
+ /* ARM->VC lock */
+ sema_init(&vc_sema, 1, "vcsema");
+
+ /* register callback for using mbox when interrupts are enabled */
+ sc->init_hook.ich_func = bcm2835_cpufreq_init;
+ sc->init_hook.ich_arg = sc;
+
+ if (config_intrhook_establish(&sc->init_hook) != 0) {
+ bus_dmamap_unload(sc->dma_tag, sc->dma_map);
+ bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map);
+ bus_dma_tag_destroy(sc->dma_tag);
+ device_printf(dev, "config_intrhook_establish failed\n");
+ return (ENOMEM);
+ }
+
+ /* this device is controlled by cpufreq(4) */
+ cpufreq_register(dev);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_detach(device_t dev)
+{
+ struct bcm2835_cpufreq_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sema_destroy(&vc_sema);
+
+ if (sc->dma_phys != 0)
+ bus_dmamap_unload(sc->dma_tag, sc->dma_map);
+ if (sc->dma_buf != NULL)
+ bus_dmamem_free(sc->dma_tag, sc->dma_buf, sc->dma_map);
+ if (sc->dma_tag != NULL)
+ bus_dma_tag_destroy(sc->dma_tag);
+
+ return (cpufreq_unregister(dev));
+}
+
+static int
+bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ uint32_t rate_hz, rem;
+ int cur_freq, resp_freq, arm_freq, min_freq, core_freq;
+
+ if (cf == NULL || cf->freq < 0)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ /* setting clock (Hz) */
+ rate_hz = (uint32_t)MHZ2HZ(cf->freq);
+ rem = rate_hz % HZSTEP;
+ rate_hz -= rem;
+ if (rate_hz == 0)
+ return (EINVAL);
+
+ /* adjust min freq */
+ min_freq = sc->arm_min_freq;
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
+ if (min_freq > cpufreq_lowest_freq)
+ min_freq = cpufreq_lowest_freq;
+
+ if (rate_hz < MHZ2HZ(min_freq) || rate_hz > MHZ2HZ(sc->arm_max_freq))
+ return (EINVAL);
+
+ /* set new value and verify it */
+ VC_LOCK(sc);
+ cur_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ resp_freq = bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM, rate_hz);
+ DELAY(TRANSITION_LATENCY);
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+
+ /*
+ * if non-turbo and lower than or equal min_freq,
+ * clock down core and sdram to default first.
+ */
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) {
+ core_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE);
+ if (rate_hz > MHZ2HZ(sc->arm_min_freq)) {
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(sc->core_max_freq));
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM,
+ MHZ2HZ(sc->sdram_max_freq));
+ DELAY(TRANSITION_LATENCY);
+ } else {
+ if (sc->core_min_freq < DEFAULT_CORE_FREQUENCY &&
+ core_freq > DEFAULT_CORE_FREQUENCY) {
+ /* first, down to 250, then down to min */
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(DEFAULT_CORE_FREQUENCY));
+ DELAY(TRANSITION_LATENCY);
+ /* reset core voltage */
+ bcm2835_cpufreq_set_voltage(sc,
+ BCM2835_MBOX_VOLTAGE_ID_CORE, 0);
+ DELAY(TRANSITION_LATENCY);
+ }
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_CORE,
+ MHZ2HZ(sc->core_min_freq));
+ DELAY(TRANSITION_LATENCY);
+ bcm2835_cpufreq_set_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_SDRAM,
+ MHZ2HZ(sc->sdram_min_freq));
+ DELAY(TRANSITION_LATENCY);
+ }
+ }
+
+ VC_UNLOCK(sc);
+
+ if (resp_freq < 0 || arm_freq < 0 || resp_freq != arm_freq) {
+ device_printf(dev, "wrong freq\n");
+ return (EIO);
+ }
+ DPRINTF("cpufreq: %d -> %d\n", cur_freq, arm_freq);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ int arm_freq;
+
+ if (cf == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
+ cf->dev = NULL;
+
+ /* get cuurent value */
+ VC_LOCK(sc);
+ arm_freq = bcm2835_cpufreq_get_clock_rate(sc,
+ BCM2835_MBOX_CLOCK_ID_ARM);
+ VC_UNLOCK(sc);
+ if (arm_freq < 0) {
+ device_printf(dev, "can't get clock\n");
+ return (EINVAL);
+ }
+
+ /* CPU clock in MHz or 100ths of a percent. */
+ cf->freq = HZ2MHZ(arm_freq);
+ /* Voltage in mV. */
+ cf->volts = CPUFREQ_VAL_UNKNOWN;
+ /* Power consumed in mW. */
+ cf->power = CPUFREQ_VAL_UNKNOWN;
+ /* Transition latency in us. */
+ cf->lat = TRANSITION_LATENCY;
+ /* Driver providing this setting. */
+ cf->dev = dev;
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
+ int *count)
+{
+ struct bcm2835_cpufreq_softc *sc;
+ int freq, min_freq, volts, rem;
+ int idx;
+
+ sc = device_get_softc(dev);
+ freq = sc->arm_max_freq;
+ min_freq = sc->arm_min_freq;
+
+ /* adjust head freq to STEP */
+ rem = freq % MHZSTEP;
+ freq -= rem;
+ if (freq < min_freq)
+ freq = min_freq;
+
+ /* if non-turbo, add extra low freq */
+ if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON)
+ if (min_freq > cpufreq_lowest_freq)
+ min_freq = cpufreq_lowest_freq;
+
+ /* from freq to min_freq */
+ for (idx = 0; idx < *count && freq >= min_freq; idx++) {
+ if (freq > sc->arm_min_freq)
+ volts = sc->max_voltage_core;
+ else
+ volts = sc->min_voltage_core;
+ sets[idx].freq = freq;
+ sets[idx].volts = volts;
+ sets[idx].lat = TRANSITION_LATENCY;
+ sets[idx].dev = dev;
+ freq -= MHZSTEP;
+ }
+ *count = ++idx;
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+ struct bcm2835_cpufreq_softc *sc;
+
+ if (sets == NULL || count == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ if (sc->arm_min_freq < 0 || sc->arm_max_freq < 0) {
+ printf("device is not configured\n");
+ return (EINVAL);
+ }
+
+ /* fill data with unknown value */
+ memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
+ /* create new array up to count */
+ bcm2835_cpufreq_make_freq_list(dev, sets, count);
+
+ return (0);
+}
+
+static int
+bcm2835_cpufreq_type(device_t dev, int *type)
+{
+
+ if (type == NULL)
+ return (EINVAL);
+ *type = CPUFREQ_TYPE_ABSOLUTE;
+
+ return (0);
+}
+
+static device_method_t bcm2835_cpufreq_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, bcm2835_cpufreq_identify),
+ DEVMETHOD(device_probe, bcm2835_cpufreq_probe),
+ DEVMETHOD(device_attach, bcm2835_cpufreq_attach),
+ DEVMETHOD(device_detach, bcm2835_cpufreq_detach),
+
+ /* cpufreq interface */
+ DEVMETHOD(cpufreq_drv_set, bcm2835_cpufreq_set),
+ DEVMETHOD(cpufreq_drv_get, bcm2835_cpufreq_get),
+ DEVMETHOD(cpufreq_drv_settings, bcm2835_cpufreq_settings),
+ DEVMETHOD(cpufreq_drv_type, bcm2835_cpufreq_type),
+
+ DEVMETHOD_END
+};
+
+static devclass_t bcm2835_cpufreq_devclass;
+static driver_t bcm2835_cpufreq_driver = {
+ "bcm2835_cpufreq",
+ bcm2835_cpufreq_methods,
+ sizeof(struct bcm2835_cpufreq_softc),
+};
+
+DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver,
+ bcm2835_cpufreq_devclass, 0, 0);
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
index 7a06eb0..4d14892 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c
@@ -83,10 +83,10 @@ struct bcm_intc_softc {
static struct bcm_intc_softc *bcm_intc_sc = NULL;
-#define intc_read_4(reg) \
- bus_space_read_4(bcm_intc_sc->intc_bst, bcm_intc_sc->intc_bsh, reg)
-#define intc_write_4(reg, val) \
- bus_space_write_4(bcm_intc_sc->intc_bst, bcm_intc_sc->intc_bsh, reg, val)
+#define intc_read_4(_sc, reg) \
+ bus_space_read_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg))
+#define intc_write_4(_sc, reg, val) \
+ bus_space_write_4((_sc)->intc_bst, (_sc)->intc_bsh, (reg), (val))
static int
bcm_intc_probe(device_t dev)
@@ -145,6 +145,7 @@ DRIVER_MODULE(intc, simplebus, bcm_intc_driver, bcm_intc_devclass, 0, 0);
int
arm_get_next_irq(int last_irq)
{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
uint32_t pending;
int32_t irq = last_irq + 1;
@@ -154,7 +155,7 @@ arm_get_next_irq(int last_irq)
/* TODO: should we mask last_irq? */
if (irq < BANK1_START) {
- pending = intc_read_4(INTC_PENDING_BASIC);
+ pending = intc_read_4(sc, INTC_PENDING_BASIC);
if ((pending & 0xFF) == 0) {
irq = BANK1_START; /* skip to next bank */
} else do {
@@ -164,7 +165,7 @@ arm_get_next_irq(int last_irq)
} while (irq < BANK1_START);
}
if (irq < BANK2_START) {
- pending = intc_read_4(INTC_PENDING_BANK1);
+ pending = intc_read_4(sc, INTC_PENDING_BANK1);
if (pending == 0) {
irq = BANK2_START; /* skip to next bank */
} else do {
@@ -174,7 +175,7 @@ arm_get_next_irq(int last_irq)
} while (irq < BANK2_START);
}
if (irq < BANK3_START) {
- pending = intc_read_4(INTC_PENDING_BANK2);
+ pending = intc_read_4(sc, INTC_PENDING_BANK2);
if (pending != 0) do {
if (pending & (1 << IRQ_BANK2(irq)))
return irq;
@@ -187,14 +188,15 @@ arm_get_next_irq(int last_irq)
void
arm_mask_irq(uintptr_t nb)
{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
dprintf("%s: %d\n", __func__, nb);
if (IS_IRQ_BASIC(nb))
- intc_write_4(INTC_DISABLE_BASIC, (1 << nb));
+ intc_write_4(sc, INTC_DISABLE_BASIC, (1 << nb));
else if (IS_IRQ_BANK1(nb))
- intc_write_4(INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb)));
+ intc_write_4(sc, INTC_DISABLE_BANK1, (1 << IRQ_BANK1(nb)));
else if (IS_IRQ_BANK2(nb))
- intc_write_4(INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb)));
+ intc_write_4(sc, INTC_DISABLE_BANK2, (1 << IRQ_BANK2(nb)));
else
printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
}
@@ -202,14 +204,15 @@ arm_mask_irq(uintptr_t nb)
void
arm_unmask_irq(uintptr_t nb)
{
+ struct bcm_intc_softc *sc = bcm_intc_sc;
dprintf("%s: %d\n", __func__, nb);
if (IS_IRQ_BASIC(nb))
- intc_write_4(INTC_ENABLE_BASIC, (1 << nb));
+ intc_write_4(sc, INTC_ENABLE_BASIC, (1 << nb));
else if (IS_IRQ_BANK1(nb))
- intc_write_4(INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb)));
+ intc_write_4(sc, INTC_ENABLE_BANK1, (1 << IRQ_BANK1(nb)));
else if (IS_IRQ_BANK2(nb))
- intc_write_4(INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb)));
+ intc_write_4(sc, INTC_ENABLE_BANK2, (1 << IRQ_BANK2(nb)));
else
printf("arm_mask_irq: Invalid IRQ number: %d\n", nb);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
index 7628eb6..f87003f 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
+#include <sys/sema.h>
#include <sys/timeet.h>
#include <sys/timetc.h>
#include <sys/watchdog.h>
@@ -88,8 +89,8 @@ struct bcm_mbox_softc {
void* intr_hl;
bus_space_tag_t bst;
bus_space_handle_t bsh;
- int valid[BCM2835_MBOX_CHANS];
int msg[BCM2835_MBOX_CHANS];
+ struct sema sema[BCM2835_MBOX_CHANS];
};
#define mbox_read_4(sc, reg) \
@@ -105,23 +106,19 @@ bcm_mbox_intr(void *arg)
uint32_t data;
uint32_t msg;
- MBOX_LOCK(sc);
while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY)) {
msg = mbox_read_4(sc, REG_READ);
dprintf("bcm_mbox_intr: raw data %08x\n", msg);
chan = MBOX_CHAN(msg);
data = MBOX_DATA(msg);
- if (sc->valid[chan]) {
+ if (sc->msg[chan]) {
printf("bcm_mbox_intr: channel %d oveflow\n", chan);
continue;
}
dprintf("bcm_mbox_intr: chan %d, data %08x\n", chan, data);
- sc->msg[chan] = data;
- sc->valid[chan] = 1;
- wakeup(&sc->msg[chan]);
-
+ sc->msg[chan] = msg;
+ sema_post(&sc->sema[chan]);
}
- MBOX_UNLOCK(sc);
}
static int
@@ -172,12 +169,13 @@ bcm_mbox_attach(device_t dev)
mtx_init(&sc->lock, "vcio mbox", NULL, MTX_DEF);
for (i = 0; i < BCM2835_MBOX_CHANS; i++) {
- sc->valid[0] = 0;
- sc->msg[0] = 0;
+ sc->msg[i] = 0;
+ sema_init(&sc->sema[i], 0, "mbox");
}
/* Read all pending messages */
- bcm_mbox_intr(sc);
+ while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY) == 0)
+ (void)mbox_read_4(sc, REG_READ);
mbox_write_4(sc, REG_CONFIG, CONFIG_DATA_IRQ);
@@ -219,10 +217,18 @@ bcm_mbox_read(device_t dev, int chan, uint32_t *data)
dprintf("bcm_mbox_read: chan %d\n", chan);
MBOX_LOCK(sc);
- while (!sc->valid[chan])
- msleep(&sc->msg[chan], &sc->lock, PZERO, "vcio mbox read", 0);
- *data = sc->msg[chan];
- sc->valid[chan] = 0;
+ while (sema_trywait(&sc->sema[chan]) == 0) {
+ /* do not unlock sc while waiting for the mbox */
+ if (sema_timedwait(&sc->sema[chan], 10*hz) == 0)
+ break;
+ printf("timeout sema for chan %d\n", chan);
+ }
+ /*
+ * get data from intr handler, the same channel is never coming
+ * because of holding sc lock.
+ */
+ *data = MBOX_DATA(sc->msg[chan]);
+ sc->msg[chan] = 0;
MBOX_UNLOCK(sc);
dprintf("bcm_mbox_read: chan %d, data %08x\n", chan, *data);
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
index 52f48e4..17e59eb 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
+++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.h
@@ -36,6 +36,7 @@
#define BCM2835_MBOX_CHAN_LEDS 4
#define BCM2835_MBOX_CHAN_BUTTONS 5
#define BCM2835_MBOX_CHAN_TS 6
-#define BCM2835_MBOX_CHANS 7
+#define BCM2835_MBOX_CHAN_PROP 8
+#define BCM2835_MBOX_CHANS 9
#endif /* _BCM2835_MBOX_H_ */
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
new file mode 100644
index 0000000..a2e212e
--- /dev/null
+++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama@peach.ne.jp>
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BCM2835_MBOX_PROP_H_
+#define _BCM2835_MBOX_PROP_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * Mailbox property interface:
+ * https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
+ */
+#define BCM2835_MBOX_CODE_REQ 0
+#define BCM2835_MBOX_CODE_RESP_SUCCESS 0x80000000
+#define BCM2835_MBOX_CODE_RESP_ERROR 0x80000001
+#define BCM2835_MBOX_TAG_VAL_LEN_RESPONSE 0x80000000
+
+struct bcm2835_mbox_hdr {
+ uint32_t buf_size;
+ uint32_t code;
+};
+
+struct bcm2835_mbox_tag_hdr {
+ uint32_t tag;
+ uint32_t val_buf_size;
+ uint32_t val_len;
+};
+
+#define BCM2835_MBOX_CLOCK_ID_EMMC 0x00000001
+#define BCM2835_MBOX_CLOCK_ID_UART 0x00000002
+#define BCM2835_MBOX_CLOCK_ID_ARM 0x00000003
+#define BCM2835_MBOX_CLOCK_ID_CORE 0x00000004
+#define BCM2835_MBOX_CLOCK_ID_V3D 0x00000005
+#define BCM2835_MBOX_CLOCK_ID_H264 0x00000006
+#define BCM2835_MBOX_CLOCK_ID_ISP 0x00000007
+#define BCM2835_MBOX_CLOCK_ID_SDRAM 0x00000008
+#define BCM2835_MBOX_CLOCK_ID_PIXEL 0x00000009
+#define BCM2835_MBOX_CLOCK_ID_PWM 0x0000000a
+
+#define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002
+#define BCM2835_MBOX_TAG_SET_CLOCK_RATE 0x00038002
+#define BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE 0x00030004
+#define BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE 0x00030007
+
+struct msg_get_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_min_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t clock_id;
+ } req;
+ struct {
+ uint32_t clock_id;
+ uint32_t rate_hz;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_TURBO_ON 1
+#define BCM2835_MBOX_TURBO_OFF 0
+
+#define BCM2835_MBOX_TAG_GET_TURBO 0x00030009
+#define BCM2835_MBOX_TAG_SET_TURBO 0x00038009
+
+struct msg_get_turbo {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t id;
+ } req;
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_turbo {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } req;
+ struct {
+ uint32_t id;
+ uint32_t level;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_VOLTAGE_ID_CORE 0x00000001
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_C 0x00000002
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_P 0x00000003
+#define BCM2835_MBOX_VOLTAGE_ID_SDRAM_I 0x00000004
+
+#define BCM2835_MBOX_TAG_GET_VOLTAGE 0x00030003
+#define BCM2835_MBOX_TAG_SET_VOLTAGE 0x00038003
+#define BCM2835_MBOX_TAG_GET_MAX_VOLTAGE 0x00030005
+#define BCM2835_MBOX_TAG_GET_MIN_VOLTAGE 0x00030008
+
+struct msg_get_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_set_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_min_voltage {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t voltage_id;
+ } req;
+ struct {
+ uint32_t voltage_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#define BCM2835_MBOX_TAG_GET_TEMPERATURE 0x00030006
+#define BCM2835_MBOX_TAG_GET_MAX_TEMPERATURE 0x0003000a
+
+struct msg_get_temperature {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t temperature_id;
+ } req;
+ struct {
+ uint32_t temperature_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+struct msg_get_max_temperature {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t temperature_id;
+ } req;
+ struct {
+ uint32_t temperature_id;
+ uint32_t value;
+ } resp;
+ } body;
+ uint32_t end_tag;
+};
+
+#endif /* _BCM2835_MBOX_PROP_H_ */
diff --git a/sys/arm/broadcom/bcm2835/files.bcm2835 b/sys/arm/broadcom/bcm2835/files.bcm2835
index 865f2d0..11158cb 100644
--- a/sys/arm/broadcom/bcm2835/files.bcm2835
+++ b/sys/arm/broadcom/bcm2835/files.bcm2835
@@ -2,6 +2,7 @@
arm/broadcom/bcm2835/bcm2835_bsc.c optional bcm2835_bsc
arm/broadcom/bcm2835/bcm2835_common.c optional fdt
+arm/broadcom/bcm2835/bcm2835_cpufreq.c standard
arm/broadcom/bcm2835/bcm2835_dma.c standard
arm/broadcom/bcm2835/bcm2835_fb.c optional sc
arm/broadcom/bcm2835/bcm2835_fbd.c optional vt
@@ -25,3 +26,4 @@ arm/arm/cpufunc_asm_armv6.S standard
kern/kern_clocksource.c standard
dev/mbox/mbox_if.m standard
+dev/ofw/ofw_cpu.c standard
diff --git a/sys/arm/broadcom/bcm2835/std.bcm2835 b/sys/arm/broadcom/bcm2835/std.bcm2835
index ebc1fb0..026f5b2 100644
--- a/sys/arm/broadcom/bcm2835/std.bcm2835
+++ b/sys/arm/broadcom/bcm2835/std.bcm2835
@@ -2,6 +2,7 @@
machine arm armv6
cpu CPU_ARM1176
+makeoptions CONF_CFLAGS="-mcpu=arm1176jzf-s -Wa,-mcpu=arm1176jzf-s"
files "../broadcom/bcm2835/files.bcm2835"
diff --git a/sys/arm/conf/APALIS-IMX6 b/sys/arm/conf/APALIS-IMX6
index 137677f..ceb21c7 100644
--- a/sys/arm/conf/APALIS-IMX6
+++ b/sys/arm/conf/APALIS-IMX6
@@ -26,6 +26,6 @@ makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
# Flattened Device Tree
-options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=apalis-imx6.dts
+options FDT
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=apalis-imx6.dts
diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP
index edfe75c..ce0f0d4 100644
--- a/sys/arm/conf/ARMADAXP
+++ b/sys/arm/conf/ARMADAXP
@@ -1,8 +1,22 @@
#
# Custom kernel for Marvell Armada XP
#
-# $FreeBSD$
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
ident MV-88F78XX0
include "../mv/armadaxp/std.mv78x60"
@@ -10,58 +24,75 @@ include "../mv/armadaxp/std.mv78x60"
options SOC_MV_ARMADAXP
makeoptions MODULES_OVERRIDE=""
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
makeoptions WERROR="-Werror"
+options HZ=1000
#options SCHED_ULE # ULE scheduler
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
-options NFSCL # Network Filesystem Client
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
-options BOOTP
-options BOOTP_NFSROOT
-options BOOTP_NFSV3
-options BOOTP_WIRED_TO=mge0
-
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT
-options ROOTDEVNAME=\"ufs:/dev/da0p1\"
-
+options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options MUTEX_NOINLINE
-options RWLOCK_NOINLINE
-options NO_FFS_SNAPSHOT
-options NO_SWAPPING
-options VFP
-
-options SMP
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-# Debugging
-#options VERBOSE_SYSINIT
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
options ALT_BREAK_TO_DEBUGGER
-options DDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
options GDB
-#options DIAGNOSTIC
#options INVARIANTS # Enable calls of extra sanity checking
#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-options KDB
-options KDB_TRACE
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS_KDB
+#options DIAGNOSTIC
#options KTR
#options KTR_VERBOSE=0
#options KTR_ENTRIES=16384
#options KTR_MASK=(KTR_SPARE2)
#options KTR_COMPILE=KTR_ALL
-#options WITNESS # Enable checks to detect deadlocks and cycles
-#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
-#options WITNESS_KDB
+
+# NFS root from boopt/dhcp
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=mge0
+
+options ROOTDEVNAME=\"ufs:/dev/da0p1\"
+
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
# Pseudo devices
device random
@@ -94,14 +125,13 @@ device mge # Marvell Gigabit Ethernet controller
device mii
device e1000phy
device bpf
-options HZ=1000
options DEVICE_POLLING
device vlan
#PCI/PCIE
device pci
-#FDT
-options FDT
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=db78460.dts
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 0363274..6f7e53e 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -1,10 +1,11 @@
+#
# BEAGLEBONE -- Custom configuration for the BeagleBone ARM development
# platforms, check out http://www.beagleboard.org/bone and
# http://www.beagleboard.org/black. This kernel config file is used for the
# original BeagleBone and the BeagleBone Black.
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -28,37 +29,47 @@ makeoptions WITHOUT_MODULES="ahc"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options PREEMPTION
options PLATFORM
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
@@ -66,19 +77,19 @@ options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-options NFSCL
-#options NFSD
-options NFSLOCKD
+# NFS server support
+#options NFSD
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=cpsw0
+# Boot device is 2nd slice on MMC/SD card
+options ROOTDEVNAME=\"ufs:mmcsd0s2\"
+
# MMC/SD/SDIO Card slot support
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
@@ -90,9 +101,6 @@ device iic
device ti_i2c
device am335x_pmic # AM335x Power Management IC (TPC65217)
-# Boot device is 2nd slice on MMC/SD card
-options ROOTDEVNAME=\"ufs:mmcsd0s2\"
-
# Console and misc
device uart
device uart_ns8250
@@ -148,6 +156,6 @@ device usb_template # Control of the gadget
device usfs
# Flattened Device Tree
-options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=beaglebone.dts
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=beaglebone.dts
diff --git a/sys/arm/conf/CHROMEBOOK-PEACH-PIT b/sys/arm/conf/CHROMEBOOK-PEACH-PIT
index 7bcfed7..e01128c 100644
--- a/sys/arm/conf/CHROMEBOOK-PEACH-PIT
+++ b/sys/arm/conf/CHROMEBOOK-PEACH-PIT
@@ -33,15 +33,15 @@ device kbdmux
device ukbd
# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
-#options BOOTP_NFSROOT
-#options BOOTP_COMPAT
-#options BOOTP
-#options BOOTP_NFSV3
-#options BOOTP_WIRED_TO=ue0
-#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/root\"
+#options NFS_ROOT # NFS usable as /, requires NFSCL
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/root\"
#FDT
-options FDT
-options FDT_DTB_STATIC
+options FDT
+options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=exynos5420-peach-pit.dts
diff --git a/sys/arm/conf/CNS11XXNAS b/sys/arm/conf/CNS11XXNAS
index 53640ff..903fd05 100644
--- a/sys/arm/conf/CNS11XXNAS
+++ b/sys/arm/conf/CNS11XXNAS
@@ -103,7 +103,7 @@ device bpf
device loop
device md
-device random # Entropy device
+device random # Entropy device
device usb
@@ -114,12 +114,12 @@ device umass
device scbus # SCSI bus (required for ATA/SCSI)
device da # Direct Access (disks)
device pass
-device cfi
+device cfi
#device udav # Davicom DM9601E USB
device geom_label
device geom_journal
-device geom_part_bsd
+device geom_part_bsd
options ROOTDEVNAME=\"ufs:da0s1a\"
diff --git a/sys/arm/conf/CUBIEBOARD b/sys/arm/conf/CUBIEBOARD
index a0b318e..40fe313 100644
--- a/sys/arm/conf/CUBIEBOARD
+++ b/sys/arm/conf/CUBIEBOARD
@@ -1,8 +1,9 @@
+#
# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
# platform, check out http://www.cubieboard.org
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -27,36 +28,46 @@ makeoptions WITHOUT_MODULES="ahc"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
@@ -64,30 +75,24 @@ options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-#options NFSCL
-#options NFSSERVER # Network Filesystem Server
-#options NFSCLIENT # Network Filesystem Client
-
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=cpsw0
-# MMC/SD/SDIO card slot support
-#device mmc # mmc/sd bus
-#device mmcsd # mmc/sd flash cards
-
# Boot device is 2nd slice on MMC/SD card
options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+# MMC/SD/SDIO Card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
# ATA controllers
#device ahci # AHCI-compatible SATA controllers
#device ata # Legacy ATA/SATA controllers
-#options ATA_STATIC_ID # Static device numbering
+#options ATA_STATIC_ID # Static device numbering
# Console and misc
device uart
@@ -134,7 +139,7 @@ device emac
device miibus
# Flattened Device Tree
-options FDT
+options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=cubieboard.dts
diff --git a/sys/arm/conf/CUBIEBOARD2 b/sys/arm/conf/CUBIEBOARD2
index 1c5184c..785364c 100644
--- a/sys/arm/conf/CUBIEBOARD2
+++ b/sys/arm/conf/CUBIEBOARD2
@@ -1,8 +1,9 @@
+#
# CUBIEBOARD2 -- Custom configuration for the CUBIEBOARD2 ARM development
# platform, check out http://www.cubieboard.org
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -20,74 +21,79 @@
ident CUBIEBOARD2
-include "../allwinner/a20/std.a20"
+include "../allwinner/a20/std.a20"
makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
-options UFS_ACL # Support for access control lists
+options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options MSDOSFS # MSDOS Filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
-options SYSVSHM # SYSV-style shared memory
-options SYSVMSG # SYSV-style message queues
-options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-options WITNESS # Enable checks to detect deadlocks and cycles
+options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-#options NFSCL
-#options NFSSERVER # Network Filesystem Server
-#options NFSCLIENT # Network Filesystem Client
-
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=cpsw0
-# MMC/SD/SDIO card slot support
-#device mmc # mmc/sd bus
-#device mmcsd # mmc/sd flash cards
-
# Boot device is 2nd slice on MMC/SD card
options ROOTDEVNAME=\"ufs:/dev/da0s2\"
+# MMC/SD/SDIO Card slot support
+#device mmc # mmc/sd bus
+#device mmcsd # mmc/sd flash cards
+
# ATA controllers
-#device ahci # AHCI-compatible SATA controllers
-#device ata # Legacy ATA/SATA controllers
-#options ATA_STATIC_ID # Static device numbering
+#device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+#options ATA_STATIC_ID # Static device numbering
# Console and misc
device uart
@@ -98,8 +104,8 @@ device md
device random # Entropy device
# I2C support
-#device iicbus
-#device iic
+#device iicbus
+#device iic
# GPIO
device gpio
@@ -114,8 +120,8 @@ device usb
options USB_DEBUG
#options USB_REQ_DEBUG
#options USB_VERBOSE
-#device uhci
-#device ohci
+#device uhci
+#device ohci
device ehci
device umass
@@ -125,7 +131,7 @@ device loop
device ether
device mii
device smscphy
-#device cpsw
+#device cpsw
device bpf
device emac
@@ -134,8 +140,7 @@ device emac
device miibus
# Flattened Device Tree
-options FDT
+options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=cubieboard2.dts
-options SMP # Enable multiple cores
diff --git a/sys/arm/conf/DIGI-CCWMX53 b/sys/arm/conf/DIGI-CCWMX53
index 7756558..20dec9c 100644
--- a/sys/arm/conf/DIGI-CCWMX53
+++ b/sys/arm/conf/DIGI-CCWMX53
@@ -22,7 +22,7 @@
include "IMX53"
ident DIGI-CCWMX53
-makeoptions WITHOUT_MODULES="ahc"
+makeoptions WITHOUT_MODULES="ahc"
# required for netbooting
#options BOOTP
@@ -34,5 +34,5 @@ makeoptions WITHOUT_MODULES="ahc"
#options ROOTDEVNAME=\"ufs:ada0s2a\"
# Flattened Device Tree
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=digi-ccwmx53.dts
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=digi-ccwmx53.dts
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index a3c57a1..ad1e74d 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -54,15 +54,15 @@ options FDT_DTB_STATIC
# Misc pseudo devices
device bpf # Required for DHCP
-device firmware # firmware(9) required for USB wlan
-device gif # IPv6 and IPv4 tunneling
+device firmware # firmware(9) required for USB wlan
+device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
-device md # Memory/malloc disk
+device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
device random # Entropy device
-device tun # Packet tunnel.
+device tun # Packet tunnel.
device ether # Required for all ethernet devices
-device vlan # 802.1Q VLAN support
+device vlan # 802.1Q VLAN support
device wlan # 802.11 WLAN support
# cam support for umass and ahci
@@ -80,66 +80,66 @@ device e1000phy
# USB
options USB_HOST_ALIGN=32 # Align DMA to cacheline
-#options USB_DEBUG # Compile in USB debug support
-device usb # Basic usb support
-device ehci # USB host controller
-device umass # Mass storage
-device uhid # Human-interface devices
-device rum # Ralink Technology RT2501USB wireless NICs
-device uath # Atheros AR5523 wireless NICs
-device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
-device urtw # Realtek RTL8187B/L USB
-device upgt # Conexant/Intersil PrismGT SoftMAC USB
-device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
# I2C (TWSI)
device iic
device iicbus
# Sound
-device sound
-device snd_uaudio
+device sound
+device snd_uaudio
#crypto
-device cesa # Marvell security engine
-device crypto
-device cryptodev
+device cesa # Marvell security engine
+device crypto
+device cryptodev
# IPSec
-device enc
-options IPSEC
-options IPSEC_NAT_T
-options TCP_SIGNATURE # include support for RFC 2385
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE # include support for RFC 2385
# IPFW
-options IPFIREWALL
-options IPFIREWALL_DEFAULT_TO_ACCEPT
-options IPFIREWALL_VERBOSE
-options IPFIREWALL_VERBOSE_LIMIT=100
-options IPFIREWALL_NAT
-options LIBALIAS
-options DUMMYNET
-options IPDIVERT
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
#PF
-device pf
-device pflog
-device pfsync
+device pf
+device pflog
+device pfsync
# ALTQ, required for PF
-options ALTQ # Basic ALTQ support
-options ALTQ_CBQ # Class Based Queueing
-options ALTQ_RED # Random Early Detection
-options ALTQ_RIO # RED In/Out
-options ALTQ_HFSC # Hierarchical Packet Scheduler
-options ALTQ_CDNR # Traffic conditioner
-options ALTQ_PRIQ # Priority Queueing
-options ALTQ_NOPCC # Required if the TSC is unusable
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
#options ALTQ_DEBUG
# Debugging
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
options ALT_BREAK_TO_DEBUGGER
options DDB
@@ -154,7 +154,7 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
# Enable these options for nfs root configured via BOOTP.
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT # NFS usable as /, requires NFSCL
#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_NFSV3
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
index 7369592..135cba0 100644
--- a/sys/arm/conf/DREAMPLUG-1001
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -57,22 +57,22 @@ options FDT_DTB_STATIC
# Misc pseudo devices
device bpf # Required for DHCP
-device firmware # firmware(9) required for USB wlan
-device gif # IPv6 and IPv4 tunneling
+device firmware # firmware(9) required for USB wlan
+device gif # IPv6 and IPv4 tunneling
device loop # Network loopback
-device md # Memory/malloc disk
+device md # Memory/malloc disk
device pty # BSD-style compatibility pseudo ttys
device random # Entropy device
-device tun # Packet tunnel.
+device tun # Packet tunnel.
device ether # Required for all ethernet devices
-device vlan # 802.1Q VLAN support
+device vlan # 802.1Q VLAN support
device wlan # 802.11 WLAN support
# cam support for umass and ahci
device scbus
device pass
device da
-device cd
+device cd
# Serial ports
device uart
@@ -84,18 +84,18 @@ device e1000phy
# USB
options USB_HOST_ALIGN=32 # Align DMA to cacheline
-#options USB_DEBUG # Compile in USB debug support
-device usb # Basic usb support
-device ehci # USB host controller
-device umass # Mass storage
-device uhid # Human-interface devices
-device rum # Ralink Technology RT2501USB wireless NICs
-device uath # Atheros AR5523 wireless NICs
-device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
-device urtw # Realtek RTL8187B/L USB
-device upgt # Conexant/Intersil PrismGT SoftMAC USB
-device u3g # USB-based 3G modems (Option, Huawei, Sierra)
+#options USB_DEBUG # Compile in USB debug support
+device usb # Basic usb support
+device ehci # USB host controller
+device umass # Mass storage
+device uhid # Human-interface devices
+device rum # Ralink Technology RT2501USB wireless NICs
+device uath # Atheros AR5523 wireless NICs
+device ural # Ralink Technology RT2500USB wireless NICs
+device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device urtw # Realtek RTL8187B/L USB
+device upgt # Conexant/Intersil PrismGT SoftMAC USB
+device u3g # USB-based 3G modems (Option, Huawei, Sierra)
# I2C (TWSI)
device iic
@@ -106,48 +106,48 @@ device mvs
device ahci
# Sound
-device sound
-device snd_uaudio
+device sound
+device snd_uaudio
#crypto
-device cesa # Marvell security engine
-device crypto
-device cryptodev
+device cesa # Marvell security engine
+device crypto
+device cryptodev
# IPSec
-device enc
-options IPSEC
-options IPSEC_NAT_T
-options TCP_SIGNATURE # include support for RFC 2385
+device enc
+options IPSEC
+options IPSEC_NAT_T
+options TCP_SIGNATURE # include support for RFC 2385
# IPFW
-options IPFIREWALL
-options IPFIREWALL_DEFAULT_TO_ACCEPT
-options IPFIREWALL_VERBOSE
-options IPFIREWALL_VERBOSE_LIMIT=100
-options IPFIREWALL_NAT
-options LIBALIAS
-options DUMMYNET
-options IPDIVERT
+options IPFIREWALL
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+options IPFIREWALL_VERBOSE
+options IPFIREWALL_VERBOSE_LIMIT=100
+options IPFIREWALL_NAT
+options LIBALIAS
+options DUMMYNET
+options IPDIVERT
#PF
-device pf
-device pflog
-device pfsync
+device pf
+device pflog
+device pfsync
# ALTQ, required for PF
-options ALTQ # Basic ALTQ support
-options ALTQ_CBQ # Class Based Queueing
-options ALTQ_RED # Random Early Detection
-options ALTQ_RIO # RED In/Out
-options ALTQ_HFSC # Hierarchical Packet Scheduler
-options ALTQ_CDNR # Traffic conditioner
-options ALTQ_PRIQ # Priority Queueing
-options ALTQ_NOPCC # Required if the TSC is unusable
+options ALTQ # Basic ALTQ support
+options ALTQ_CBQ # Class Based Queueing
+options ALTQ_RED # Random Early Detection
+options ALTQ_RIO # RED In/Out
+options ALTQ_HFSC # Hierarchical Packet Scheduler
+options ALTQ_CDNR # Traffic conditioner
+options ALTQ_PRIQ # Priority Queueing
+options ALTQ_NOPCC # Required if the TSC is unusable
#options ALTQ_DEBUG
# Debugging
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
options ALT_BREAK_TO_DEBUGGER
options DDB
@@ -162,7 +162,7 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
# Enable these options for nfs root configured via BOOTP.
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT # NFS usable as /, requires NFSCL
#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_NFSV3
@@ -178,7 +178,7 @@ options ROOTDEVNAME=\"ufs:/dev/da1s1a\"
# create a kernel config file that looks like this:
#
# include DREAMPLUG-1001
-# nomakeoptions FDT_DTS_FILE
+# nomakeoptions FDT_DTS_FILE
# makeoptions FDT_DTS_FILE=dreamplug-1001N.dts
# device nand
diff --git a/sys/arm/conf/EA3250 b/sys/arm/conf/EA3250
index 82bc386..d2d691b 100644
--- a/sys/arm/conf/EA3250
+++ b/sys/arm/conf/EA3250
@@ -19,7 +19,7 @@ options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
options NFSCL # Network Filesystem Client
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options TMPFS # Efficient memory filesystem
diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX
index 677d73d..459cd79 100644
--- a/sys/arm/conf/EFIKA_MX
+++ b/sys/arm/conf/EFIKA_MX
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Efika MX Smarttop/Smartbook boards
#
# For more information on this file, please read the config(5) manual page,
@@ -21,34 +22,32 @@ ident EFIKA_MX
include "../freescale/imx/std.imx51"
-makeoptions WITHOUT_MODULES="ahc"
-
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
-#options DEBUG
+makeoptions WITHOUT_MODULES="ahc"
options SCHED_4BSD # 4BSD scheduler
-#options PREEMPTION # Enable kernel thread preemption
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
-#options INET6 # IPv6 communications protocols
-#options SCTP # Stream Control Transmission Protocol
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
#options MD_ROOT # MD is a potential root device
options NFSCL # New Network Filesystem Client
#options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
-options TMPFS # Efficient memory filesystem
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
-#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID Partition Tables.
options GEOM_LABEL # Provides labelization
#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
@@ -59,16 +58,34 @@ options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options PLATFORM
options INCLUDE_CONFIG_FILE # Include this file in kernel
-options VFP # vfp/neon
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB
+options DEADLKRES # Enable the deadlock resolver
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
-# required for netbooting
+# NFS root from boopt/dhcp
#options BOOTP
-#options BOOTP_COMPAT
#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=ue0
-#
+
options ROOTDEVNAME=\"ufs:ada0s2a\"
@@ -79,18 +96,6 @@ options ROOTDEVNAME=\"ufs:ada0s2a\"
#options NO_SYSCTL_DESCR
#options RWLOCK_NOINLINE
-# Debugging support. Always need this:
-options KDB # Enable kernel debugger support.
-# For minimum debugger support (stable branch) use:
-#options KDB_TRACE # Print a stack trace for a panic.
-# For full debugger support use this instead:
-options DDB # Support DDB.
-#options GDB # Support remote GDB.
-options DEADLKRES # Enable the deadlock resolver
-options INVARIANTS # Enable calls of extra sanity checking
-options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-options WITNESS # Enable checks to detect deadlocks and cycles
-
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
# Note that 'bpf' is required for DHCP.
@@ -162,15 +167,15 @@ device wlan_tkip # 802.11 TKIP support
device wlan_amrr # AMRR transmit rate control algorithm
# Flattened Device Tree
-options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=efikamx.dts
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=efikamx.dts
# NOTE: serial console will be disabled if syscons enabled
# Uncomment following lines for framebuffer/syscons support
device sc
device kbdmux
-options SC_DFLT_FONT # compile font in
-makeoptions SC_DFLT_FONT=cp437
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
device ukbd # Allow keyboard like HIDs to control console
device ums
diff --git a/sys/arm/conf/EXYNOS5.common b/sys/arm/conf/EXYNOS5.common
index 7cd577d..0179d5b 100644
--- a/sys/arm/conf/EXYNOS5.common
+++ b/sys/arm/conf/EXYNOS5.common
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Samsung Exynos 5 SoC.
#
# For more information on this file, please read the config(5) manual page,
@@ -20,70 +21,72 @@
makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
makeoptions WERROR="-Werror"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID partition tables
-options TMPFS # Efficient memory filesystem
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
-options SOFTUPDATES
+options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
-options KTRACE
+options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options KBD_INSTALL_CDEV
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-options SMP
-
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
-#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
#options INVARIANTS # Enable calls of extra sanity checking
#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-#options WITNESS # Enable checks to detect deadlocks and cycles
-#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-options NFSCL # Network Filesystem Client
-options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
-#options BOOTP_NFSROOT
-#options BOOTP_COMPAT
-#options BOOTP
-#options BOOTP_NFSV3
-#options BOOTP_WIRED_TO=ue0
+options ROOTDEVNAME=\"ufs:/dev/da0\"
+# MMC/SD/SDIO Card slot support
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
device dwmmc
-options ROOTDEVNAME=\"ufs:/dev/da0\"
-
# Pseudo devices
device loop
@@ -96,8 +99,8 @@ device gpio
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
device usb
options USB_DEBUG
-#options USB_REQ_DEBUG
-#options USB_VERBOSE
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
#device musb
device ehci
#device ohci
diff --git a/sys/arm/conf/HL201 b/sys/arm/conf/HL201
index efdea82..8a15544 100644
--- a/sys/arm/conf/HL201
+++ b/sys/arm/conf/HL201
@@ -143,5 +143,5 @@ options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=hl201.dts
options EARLY_PRINTF
-options SOCDEV_PA=0xfc000000
+options SOCDEV_PA=0xfc000000
options SOCDEV_VA=0xdc000000
diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53
index 5fd5697..12cd4cf 100644
--- a/sys/arm/conf/IMX53
+++ b/sys/arm/conf/IMX53
@@ -1,3 +1,4 @@
+#
# Kernel configuration for i.MX53 boards
#
# For more information on this file, please read the config(5) manual page,
@@ -21,32 +22,29 @@ ident IMX53
include "../freescale/imx/std.imx53"
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
-#options DEBUG
-
options SCHED_4BSD # 4BSD scheduler
-#options PREEMPTION # Enable kernel thread preemption
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-#options SCTP # Stream Control Transmission Protocol
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
-#options MD_ROOT # MD is a potential root device
+options QUOTA # Enable disk quotas for UFS
options NFSCL # New Network Filesystem Client
#options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
-options TMPFS # Efficient memory filesystem
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
-#options PROCFS # Process filesystem (requires PSEUDOFS)
+options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID Partition Tables.
options GEOM_LABEL # Provides labelization
#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
@@ -57,27 +55,31 @@ options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options PLATFORM
options INCLUDE_CONFIG_FILE # Include this file in kernel
-options VFP # vfp/neon
-
-# kernel/memory size reduction
-#options MUTEX_NOINLINE
-#options NO_FFS_SNAPSHOT
-#options NO_SWAPPING
-#options NO_SYSCTL_DESCR
-#options RWLOCK_NOINLINE
+options VFP # Enable floating point hardware support
-# Debugging support. Always need this:
-options KDB # Enable kernel debugger support.
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
# For minimum debugger support (stable branch) use:
-#options KDB_TRACE # Print a stack trace for a panic.
+#options KDB_TRACE # Print a stack trace for a panic
# For full debugger support use this instead:
-options DDB # Support DDB.
-#options GDB # Support remote GDB.
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB
options DEADLKRES # Enable the deadlock resolver
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+# kernel/memory size reduction
+#options MUTEX_NOINLINE
+#options NO_FFS_SNAPSHOT
+#options NO_SWAPPING
+#options NO_SYSCTL_DESCR
+#options RWLOCK_NOINLINE
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
@@ -161,12 +163,12 @@ device wlan_amrr # AMRR transmit rate control algorithm
# Flattened Device Tree
-options FDT
+options FDT # Configure using FDT/DTB data
# NOTE: serial console will be disabled if syscons enabled
# Uncomment following lines for framebuffer/syscons support
#device sc
#device vt
#device kbdmux
-#options SC_DFLT_FONT # compile font in
-#makeoptions SC_DFLT_FONT=cp437
+#options SC_DFLT_FONT # compile font in
+#makeoptions SC_DFLT_FONT=cp437
diff --git a/sys/arm/conf/IMX53-QSB b/sys/arm/conf/IMX53-QSB
index fdaa4ec..fdde591 100644
--- a/sys/arm/conf/IMX53-QSB
+++ b/sys/arm/conf/IMX53-QSB
@@ -34,5 +34,5 @@ options HZ=250 # 4ms scheduling quantum
#options ROOTDEVNAME=\"ufs:ada0s2a\"
# Flattened Device Tree
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=imx53-qsb.dts
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=imx53-qsb.dts
diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6
index 007862b..bdaab26 100644
--- a/sys/arm/conf/IMX6
+++ b/sys/arm/conf/IMX6
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Freescale i.MX6 systems.
#
# For more information on this file, please read the config(5) manual page,
@@ -20,140 +21,143 @@
ident IMX6
include "../freescale/imx/std.imx6"
-options HZ=500 # Scheduling quantum is 2 milliseconds.
-options SCHED_ULE # ULE scheduler
-options PREEMPTION # Enable kernel thread preemption
-options INET # InterNETworking
-options INET6 # IPv6 communications protocols
-options SCTP # Stream Control Transmission Protocol
-options FFS # Berkeley Fast Filesystem
-options SOFTUPDATES # Enable FFS soft updates support
-options UFS_ACL # Support for access control lists
-options UFS_DIRHASH # Improve performance on big directories
-options UFS_GJOURNAL # Enable gjournal-based UFS journaling
-#options MD_ROOT # MD is a potential root device
-options NFSCL # New Network Filesystem Client
-#options NFSD # New Network Filesystem Server
-options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCL
+options HZ=500 # Scheduling quantum is 2 milliseconds.
+options SCHED_ULE # ULE scheduler
+options PREEMPTION # Enable kernel thread preemption
+options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
+options FFS # Berkeley Fast Filesystem
+options SOFTUPDATES # Enable FFS soft updates support
+options UFS_ACL # Support for access control lists
+options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
options TMPFS # Efficient memory filesystem
-options MSDOSFS # MSDOS Filesystem
-options CD9660 # ISO 9660 Filesystem
-#options PROCFS # Process filesystem (requires PSEUDOFS)
-options PSEUDOFS # Pseudo-filesystem framework
+options GEOM_PART_GPT # GUID Partition Tables
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID Partition Tables.
-options GEOM_LABEL # Provides labelization
-options KTRACE # ktrace(1) support
-options SYSVSHM # SYSV-style shared memory
-options SYSVMSG # SYSV-style message queues
-options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
-options INCLUDE_CONFIG_FILE # Include this file in kernel
-
-# Debugging support. Always need this:
-options KDB # Enable kernel debugger support.
-# For minimum debugger support use KDB_TRACE, for interactive use DDB.
-#options KDB_TRACE # Print a stack trace for a panic.
-options DDB # Support DDB.
+options GEOM_LABEL # Provides labelization
+options KTRACE # ktrace(1) support
+options SYSVSHM # SYSV-style shared memory
+options SYSVMSG # SYSV-style message queues
+options SYSVSEM # SYSV-style semaphores
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options INCLUDE_CONFIG_FILE # Include this file in kernel
+options PLATFORM
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
# For full debugger support use this instead:
-#options GDB # Support remote GDB.
+options DDB # Enable the kernel debugger
+#options GDB # Support remote GDB.
# Other debugging options...
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
-options ALT_BREAK_TO_DEBUGGER # Use <CR><tilde><ctrl-b> to enter debugger.
-#options DEBUG
-#options DEADLKRES # Enable the deadlock resolver
-#options INVARIANTS # Enable calls of extra sanity checking
-#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-#options WITNESS # Enable checks to detect deadlocks and cycles
+options ALT_BREAK_TO_DEBUGGER # Use <CR><tilde><ctrl-b> to enter debugger.
+#options DEADLKRES # Enable the deadlock resolver
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ffec0
+
+# U-Boot stuff lives on slice 1, FreeBSD on slice 2.
+options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
# Pseudo devices.
-device loop # Network loopback
-device random # Entropy device
-device vlan # 802.1Q VLAN support
-device tun # Packet tunnel.
-device md # Memory "disks"
-#device gif # IPv6 and IPv4 tunneling
-#device firmware # firmware assist module
-device ether # Ethernet support
-device miibus # Required for ethernet
-device bpf # Berkeley packet filter (required for DHCP)
+device loop # Network loopback
+device random # Entropy device
+device vlan # 802.1Q VLAN support
+device tun # Packet tunnel.
+device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device firmware # firmware assist module
+device ether # Ethernet support
+device miibus # Required for ethernet
+device bpf # Berkeley packet filter (required for DHCP)
# General-purpose input/output
-device gpio
+device gpio
# Serial (COM) ports
-device uart # Multi-uart driver
+device uart # Multi-uart driver
# SDCard
-device sdhci # SD controller
-device mmc # SD/MMC protocol
-device mmcsd # SDCard disk device
+device sdhci # SD controller
+device mmc # SD/MMC protocol
+device mmcsd # SDCard disk device
# SCSI peripherals
-device scbus # SCSI bus (required for ATA/SCSI)
-device da # Direct Access (disks)
-device cd # CD
-device pass # Passthrough device (direct ATA/SCSI access)
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
# USB support
-#options USB_DEBUG # enable debug msgs
-device ehci # OHCI USB interface
-device usb # USB Bus (required)
-device umass # Disks/Mass storage - Requires scbus and da
-device uhid # "Human Interface Devices"
-device u3g # USB modems
-#device ukbd # Allow keyboard like HIDs to control console
-#device ums # USB mouse
+#options USB_DEBUG # enable debug msgs
+device ehci # OHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+device u3g # USB modems
+#device ukbd # Allow keyboard like HIDs to control console
+#device ums # USB mouse
# USB Ethernet, requires miibus
-#device aue # ADMtek USB Ethernet
-#device axe # ASIX Electronics USB Ethernet
-#device cdce # Generic USB over Ethernet
-#device cue # CATC USB Ethernet
-#device kue # Kawasaki LSI USB Ethernet
-#device rue # RealTek RTL8150 USB Ethernet
-#device udav # Davicom DM9601E USB
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
# USB Wireless
-#device rum # Ralink Technology RT2501USB wireless NICs
+#device rum # Ralink Technology RT2501USB wireless NICs
# Wireless NIC cards
-#device wlan # 802.11 support
-#device wlan_wep # 802.11 WEP support
-#device wlan_ccmp # 802.11 CCMP support
-#device wlan_tkip # 802.11 TKIP support
-#device wlan_amrr # AMRR transmit rate control algorithm
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
# NOTE: serial console will be disabled if syscons enabled
# Uncomment following lines for framebuffer/syscons support
# Wandboard has no video console support yet.
-#device sc
-#device kbdmux
-#options SC_DFLT_FONT # compile font in
-#makeoptions SC_DFLT_FONT=cp437
-
-# required for netbooting
-#options BOOTP
-#options BOOTP_COMPAT
-#options BOOTP_NFSROOT
-#options BOOTP_NFSV3
-#options BOOTP_WIRED_TO=ffec0
-
-# U-Boot stuff lives on slice 1, FreeBSD on slice 2.
-options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
+#device sc
+#device kbdmux
+#options SC_DFLT_FONT # compile font in
+#makeoptions SC_DFLT_FONT=cp437
-# ARM and SoC-specific options
-options FDT # Configure using FDT/DTB data.
-options SMP # Enable multiple cores
-options VFP # Enable floating point hardware support
-options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
# SoC-specific devices
-device ffec # Freescale Fast Ethernet Controller
-device fsliic # Freescale i2c/iic
-device iic # iic protocol
-device iicbus # iic bus
-#device imxwdt # Watchdog. WARNING: can't be disabled!!!
+device ffec # Freescale Fast Ethernet Controller
+device fsliic # Freescale i2c/iic
+device iic # iic protocol
+device iicbus # iic bus
+#device imxwdt # Watchdog. WARNING: can't be disabled!!!
diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD
index cc345cb..7a71d12 100644
--- a/sys/arm/conf/PANDABOARD
+++ b/sys/arm/conf/PANDABOARD
@@ -1,8 +1,9 @@
+#
# PANDABOARD -- Custom configuration for the PandaBoard ARM development
# platform, check out www.pandaboard.org
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -28,44 +29,53 @@ hints "PANDABOARD.hints"
include "../ti/omap4/pandaboard/std.pandaboard"
-#To statically compile in device wiring instead of /boot/device.hints
makeoptions MODULES_OVERRIDE=""
-makeoptions WITHOUT_MODULES="ahc"
+makeoptions WITHOUT_MODULES="ahc"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options PREEMPTION
options PLATFORM
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
-options SMP # Enable multiple cores
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
#options INVARIANTS # Enable calls of extra sanity checking
#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
@@ -73,14 +83,10 @@ options DDB # Enable the kernel debugger
#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-options NFSCL
-
-# NFS root
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=ue0
@@ -146,6 +152,6 @@ device twl_vreg
device twl_clks
# Flattened Device Tree
-options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=pandaboard.dts
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=pandaboard.dts
diff --git a/sys/arm/conf/RK3188 b/sys/arm/conf/RK3188
index d6a26dd..ab9d20a 100644
--- a/sys/arm/conf/RK3188
+++ b/sys/arm/conf/RK3188
@@ -1,7 +1,8 @@
+#
# Kernel configuration for Rockchip RK3188 systems.
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -23,56 +24,61 @@ include "../rockchip/std.rk30xx"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
-options SMP # Enable multiple cores
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
-#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
-#options INVARIANTS # Enable calls of extra sanity checking
-#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
options DIAGNOSTIC
-# NFS support
-#options NFSCL
-#options NFSSERVER # Network Filesystem Server
-#options NFSCLIENT # Network Filesystem Client
+# Boot device is 2nd slice on USB
+options ROOTDEVNAME=\"ufs:/dev/da0s2\"
-# MMC/SD/SDIO card slot support
+# MMC/SD/SDIO Card slot support
#device mmc # mmc/sd bus
#device mmcsd # mmc/sd flash cards
-# Boot device is 2nd slice on USB
-options ROOTDEVNAME=\"ufs:/dev/da0s2\"
-
# Console and misc
device uart
device uart_ns8250
@@ -96,8 +102,8 @@ device pass
options USB_HOST_ALIGN=32 # Align usb buffers to cache line size.
device usb
options USB_DEBUG
-#options USB_REQ_DEBUG
-#options USB_VERBOSE
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
device dwcotg # DWC OTG controller
device umass
@@ -109,10 +115,10 @@ device mii
device bpf
# Wireless NIC cards
-options IEEE80211_DEBUG
-options IEEE80211_AMPDU_AGE
-options IEEE80211_SUPPORT_MESH
-options IEEE80211_SUPPORT_TDMA
+options IEEE80211_DEBUG
+options IEEE80211_AMPDU_AGE
+options IEEE80211_SUPPORT_MESH
+options IEEE80211_SUPPORT_TDMA
device wlan # 802.11 support
device wlan_wep # 802.11 WEP support
device wlan_ccmp # 802.11 CCMP support
@@ -121,8 +127,9 @@ device urtwn
device urtwnfw
device firmware # Used by the above
-# USB ethernet support, requires miibus
+# USB Ethernet support, requires miibus
device miibus
device udav
-options FDT # Configure using FDT/DTB data.
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
diff --git a/sys/arm/conf/RPI-B b/sys/arm/conf/RPI-B
index 322a4ec..c1013d1 100644
--- a/sys/arm/conf/RPI-B
+++ b/sys/arm/conf/RPI-B
@@ -1,7 +1,8 @@
+#
# RPI-B -- Custom configuration for the Raspberry Pi
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -11,8 +12,8 @@
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
-# device lines is also present in the ../../conf/NOTES and NOTES files.
-# If you are in doubt as to the purpose or necessity of a line, check first
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
@@ -21,10 +22,9 @@ ident RPI-B
include "../broadcom/bcm2835/std.rpi"
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options HZ=100
-
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options SCTP # Stream Control Transmission Protocol
@@ -32,42 +32,62 @@ options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
-device snp
-
-options NFSCL # Network Filesystem Client
-
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
-#options BOOTP_NFSROOT
-#options BOOTP_COMPAT
-#options BOOTP
-#options BOOTP_NFSV3
-#options BOOTP_WIRED_TO=ue0
-
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-#options ROOTDEVNAME=\"ufs:mmcsd0s2\"
-
-options PREEMPTION
options PLATFORM
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ue0
+
+#options ROOTDEVNAME=\"ufs:mmcsd0s2\"
device bpf
device loop
device ether
device uart
-device pl011
-
device pty
+device snp
+device pl011
# Comment following lines for boot console on serial port
device vt
@@ -86,11 +106,6 @@ device iic
device iicbus
device bcm2835_bsc
-options KDB
-options DDB # Enable the kernel debugger
-options INVARIANTS # Enable calls of extra sanity checking
-options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-
device md
device random # Entropy device
@@ -114,10 +129,8 @@ device spibus
device bcm2835_spi
# Flattened Device Tree
-options FDT
+options FDT # Configure using FDT/DTB data
# Note: DTB is normally loaded and modified by RPi boot loader, then
# handed to kernel via U-Boot and ubldr.
-#options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=rpi.dts
-
-options VFP # vfp/neon
+#options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=rpi.dts
diff --git a/sys/arm/conf/SAM9260EK b/sys/arm/conf/SAM9260EK
index c3cba33..dd0d52e 100644
--- a/sys/arm/conf/SAM9260EK
+++ b/sys/arm/conf/SAM9260EK
@@ -180,5 +180,5 @@ device nand # NAND interface on CS3
#makeoptions FDT_DTS_FILE=sam9260ek.dts
options EARLY_PRINTF
-options SOCDEV_PA=0xfc000000
+options SOCDEV_PA=0xfc000000
options SOCDEV_VA=0xdc000000
diff --git a/sys/arm/conf/SOCKIT b/sys/arm/conf/SOCKIT
index 5a9ade5..744559a 100644
--- a/sys/arm/conf/SOCKIT
+++ b/sys/arm/conf/SOCKIT
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC).
#
# For more information on this file, please read the config(5) manual page,
@@ -22,44 +23,51 @@ include "../altera/socfpga/std.socfpga"
makeoptions MODULES_OVERRIDE=""
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
makeoptions WERROR="-Werror"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID partition tables
-options TMPFS # Efficient memory filesystem
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
-options SOFTUPDATES
+options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
-options KTRACE
+options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options KBD_INSTALL_CDEV
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-options SMP
-
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
@@ -67,25 +75,20 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-options NFSCL # Network Filesystem Client
-options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
-
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=ue0
+options ROOTDEVNAME=\"ufs:/dev/da0\"
+
+# MMC/SD/SDIO Card slot support
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
device dwmmc
-options ROOTDEVNAME=\"ufs:/dev/da0\"
-
# Pseudo devices
device loop
@@ -132,7 +135,7 @@ device miibus
device axe # ASIX Electronics USB Ethernet
device bpf # Berkeley packet filter
-#FDT
-options FDT
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=socfpga-sockit.dts
diff --git a/sys/arm/conf/SOCKIT-BERI b/sys/arm/conf/SOCKIT-BERI
index 76306de..918da53 100644
--- a/sys/arm/conf/SOCKIT-BERI
+++ b/sys/arm/conf/SOCKIT-BERI
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC).
#
# For more information on this file, please read the config(5) manual page,
@@ -22,44 +23,51 @@ include "../altera/socfpga/std.socfpga"
makeoptions MODULES_OVERRIDE=""
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
makeoptions WERROR="-Werror"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options GEOM_PART_GPT # GUID partition tables
-options TMPFS # Efficient memory filesystem
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
-options SOFTUPDATES
+options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
-options KTRACE
+options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options KBD_INSTALL_CDEV
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-options SMP
-
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
@@ -67,25 +75,20 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options DIAGNOSTIC
-# NFS support
-options NFSCL # Network Filesystem Client
-options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
-
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
+# NFS root from boopt/dhcp
+#options BOOTP
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
-#options BOOTP
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=ue0
+options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
+
+# MMC/SD/SDIO Card slot support
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
device dwmmc
-options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
-
# Pseudo devices
device loop
@@ -139,7 +142,7 @@ device miibus
device axe # ASIX Electronics USB Ethernet
device bpf # Berkeley packet filter
-#FDT
-options FDT
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=socfpga-sockit-beri.dts
diff --git a/sys/arm/conf/VERSATILEPB b/sys/arm/conf/VERSATILEPB
index fb2087a..2132389 100644
--- a/sys/arm/conf/VERSATILEPB
+++ b/sys/arm/conf/VERSATILEPB
@@ -1,7 +1,8 @@
+#
# VERSATILEPB - Configuration for QEMU version of Versatile Platform Board
#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
@@ -11,8 +12,8 @@
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
-# device lines is also present in the ../../conf/NOTES and NOTES files.
-# If you are in doubt as to the purpose or necessity of a line, check first
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
@@ -29,36 +30,53 @@ makeoptions KERNVIRTADDR=0xc0100000
options KERNPHYSADDR=0x00100000
makeoptions KERNPHYSADDR=0x00100000
options PHYSADDR=0x00000000
-options FREEBSD_BOOT_LOADER
-options LINUX_BOOT_ABI
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options HZ=100
-
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
+options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-device snp
-
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
+options MSDOSFS # MSDOS Filesystem
+options CD9660 # ISO 9660 Filesystem
+options PROCFS # Process filesystem (requires PSEUDOFS)
+options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
-options PSEUDOFS # Pseudo-filesystem framework
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
-options ROOTDEVNAME=\"ufs:da0s1a\"
-options VFP # vfp/neon
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options LINUX_BOOT_ABI # Process metadata passed from Linux boot loaders
+options VFP # Enable floating point hardware support
-options PREEMPTION
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+
+options ROOTDEVNAME=\"ufs:da0s1a\"
device bpf
device loop
@@ -72,6 +90,7 @@ device pl011
device pl190
device pty
+device snp
device pci
@@ -87,18 +106,13 @@ device pass # Passthrough device (direct ATA/SCSI access)
# Comment following lines for headless setup
device sc
device kbdmux
-options SC_DFLT_FONT # compile font in
-makeoptions SC_DFLT_FONT=cp437
-
-options KDB
-options DDB # Enable the kernel debugger
-options INVARIANTS # Enable calls of extra sanity checking
-options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options SC_DFLT_FONT # compile font in
+makeoptions SC_DFLT_FONT=cp437
device md
device random # Entropy device
# Flattened Device Tree
-options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=versatilepb.dts
+options FDT # Configure using FDT/DTB data
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=versatilepb.dts
diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID
index e2e1def..7ff206e 100644
--- a/sys/arm/conf/VYBRID
+++ b/sys/arm/conf/VYBRID
@@ -1,3 +1,4 @@
+#
# Kernel configuration for Vybrid Family boards.
#
# For more information on this file, please read the config(5) manual page,
@@ -23,75 +24,79 @@ include "../freescale/vybrid/std.vybrid"
makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
makeoptions WERROR="-Werror"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
-options SOFTUPDATES
+options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
+#options NANDFS # NAND Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
-#options NANDFS # NAND Filesystem
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options COMPAT_43 # Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
-options KTRACE
+options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options KBD_INSTALL_CDEV
-options PREEMPTION
-options FREEBSD_BOOT_LOADER
-options MUTEX_NOINLINE
-options RWLOCK_NOINLINE
-options NO_FFS_SNAPSHOT
-options NO_SWAPPING
-options VFP # vfp/neon
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+#options SMP # Enable multiple cores
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
options BREAK_TO_DEBUGGER
-#options VERBOSE_SYSINIT # Enable verbose sysinit messages
-options KDB
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
options DDB # Enable the kernel debugger
-#options INVARIANTS # Enable calls of extra sanity checking
-#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-#options WITNESS # Enable checks to detect deadlocks and cycles
-#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
-#options DIAGNOSTIC
-
-# NFS support
-options NFSCL # Network Filesystem Client
-options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
-
-# Uncomment this for NFS root
-#options NFS_ROOT # NFS usable as /, requires NFSCL
-#options BOOTP_NFSROOT
-#options BOOTP_COMPAT
-#options BOOTP
-#options BOOTP_NFSV3
-#options BOOTP_WIRED_TO=ffec0
-
-device mmc # mmc/sd bus
-device mmcsd # mmc/sd flash cards
-device sdhci # generic sdhci
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=ffec0
#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/cosmic\"
#options ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\"
options ROOTDEVNAME=\"ufs:/dev/da0\"
-#options SMP
+options MUTEX_NOINLINE
+options RWLOCK_NOINLINE
+options NO_FFS_SNAPSHOT
+options NO_SWAPPING
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+device sdhci # generic sdhci
# Pseudo devices
@@ -105,8 +110,8 @@ device gpio
options USB_HOST_ALIGN=32 # Align usb buffers to cache line size.
device usb
options USB_DEBUG
-#options USB_REQ_DEBUG
-#options USB_VERBOSE
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
#device musb
device ehci
#device ohci
@@ -150,4 +155,5 @@ device vt
device kbdmux
device ukbd
-options FDT
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
diff --git a/sys/arm/conf/WANDBOARD-DUAL b/sys/arm/conf/WANDBOARD-DUAL
index 1e690c9..66e2535 100644
--- a/sys/arm/conf/WANDBOARD-DUAL
+++ b/sys/arm/conf/WANDBOARD-DUAL
@@ -23,6 +23,6 @@ include "IMX6"
ident WANDBOARD-DUAL
# Flattened Device Tree
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=wandboard-dual.dts
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=wandboard-dual.dts
diff --git a/sys/arm/conf/WANDBOARD-QUAD b/sys/arm/conf/WANDBOARD-QUAD
index 121e712..830a445 100644
--- a/sys/arm/conf/WANDBOARD-QUAD
+++ b/sys/arm/conf/WANDBOARD-QUAD
@@ -23,6 +23,6 @@ include "IMX6"
ident WANDBOARD-QUAD
# Flattened Device Tree
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=wandboard-quad.dts
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=wandboard-quad.dts
diff --git a/sys/arm/conf/WANDBOARD-SOLO b/sys/arm/conf/WANDBOARD-SOLO
index 424bc5f..39a0c7c 100644
--- a/sys/arm/conf/WANDBOARD-SOLO
+++ b/sys/arm/conf/WANDBOARD-SOLO
@@ -23,6 +23,6 @@ include "IMX6"
ident WANDBOARD-SOLO
# Flattened Device Tree
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=wandboard-solo.dts
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=wandboard-solo.dts
diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD
index 8ec0df1..e1200bf 100644
--- a/sys/arm/conf/ZEDBOARD
+++ b/sys/arm/conf/ZEDBOARD
@@ -1,73 +1,86 @@
+#
# ZEDBOARD -- Custom configuration for the Xilinx Zynq-7000 based
# ZedBoard (www.zedboard.org)
-#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
-#
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
-#
+#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
-#
+#
# An exhaustive list of options and more detailed explanations of the
-# device lines is also present in the ../../conf/NOTES and NOTES files.
-# If you are in doubt as to the purpose or necessity of a line, check first
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
-#
+#
# $FreeBSD$
ident ZEDBOARD
-include "../xilinx/zedboard/std.zedboard"
+include "../xilinx/zedboard/std.zedboard"
makeoptions MODULES_OVERRIDE=""
makeoptions WITHOUT_MODULES="ahc"
options SCHED_4BSD # 4BSD scheduler
+options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
+options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
-# options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
-
-options NFSCL # Network Filesystem Client
-# options NFSSD # Network Filesystem Server
-# options NFSLOCKD # Network Lock Manager
-# options NFS_ROOT # NFS usable as /, requires NFSCL
-# options BOOTP_NFSROOT
-# options BOOTP
-
-options GEOM_PART_BSD # BSD partition scheme
-options GEOM_PART_MBR # MBR partition scheme
-options TMPFS # Efficient memory filesystem
+options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
+options NFSCL # New Network Filesystem Client
+#options NFSSD # Network Filesystem Server
+options NFSLOCKD # Network Lock Manager
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
+options TMPFS # Efficient memory filesystem
+options GEOM_PART_GPT # GUID Partition Tables
+options GEOM_PART_BSD # BSD partition scheme
+options GEOM_PART_MBR # MBR partition scheme
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
-options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
-options FREEBSD_BOOT_LOADER
-options VFP # vfp/neon
-options SMP # Symmetric MultiProcessor Kernel
+options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
+options KBD_INSTALL_CDEV # install a CDEV entry in /dev
+options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
+options VFP # Enable floating point hardware support
+options SMP # Enable multiple cores
-# Debugging
+# Debugging for use in -current
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
-options DDB
-options KDB
-# options BREAK_TO_DEBUGGER
+#options BREAK_TO_DEBUGGER
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+#options INVARIANTS # Enable calls of extra sanity checking
+#options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+#options WITNESS # Enable checks to detect deadlocks and cycles
+#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
-# options INVARIANTS # Enable calls of extra sanity checking
-# options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
-# options WITNESS # Enable checks to detect deadlocks and cycles
-# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
device loop
device random
@@ -98,7 +111,7 @@ device axe # USB-Ethernet
# Flattened Device Tree
-options FDT
-# options FDT_DTB_STATIC
-# makeoptions FDT_DTS_FILE=zedboard.dts
+options FDT # Configure using FDT/DTB data
+#options FDT_DTB_STATIC
+#makeoptions FDT_DTS_FILE=zedboard.dts
diff --git a/sys/arm/freescale/imx/imx51_machdep.c b/sys/arm/freescale/imx/imx51_machdep.c
index 8ab6541..5d8f380 100644
--- a/sys/arm/freescale/imx/imx51_machdep.c
+++ b/sys/arm/freescale/imx/imx51_machdep.c
@@ -39,36 +39,28 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/devmap.h>
#include <machine/machdep.h>
-#include <machine/platform.h>
+#include <machine/platformvar.h>
#include <arm/freescale/imx/imx_machdep.h>
-vm_offset_t
-platform_lastaddr(void)
+#include "platform_if.h"
+
+static vm_offset_t
+imx51_lastaddr(platform_t plat)
{
return (arm_devmap_lastaddr());
}
-void
-platform_probe_and_attach(void)
+static int
+imx51_attach(platform_t plat)
{
/* XXX - Get rid of this stuff soon. */
boothowto |= RB_VERBOSE|RB_MULTIPLE;
bootverbose = 1;
-}
-
-void
-platform_gpio_init(void)
-{
-
-}
-
-void
-platform_late_init(void)
-{
+ return (0);
}
/*
@@ -78,8 +70,8 @@ platform_late_init(void)
*
* Notably missing are entries for GPU, IPU, in general anything video related.
*/
-int
-platform_devmap_init(void)
+static int
+imx51_devmap_init(platform_t plat)
{
arm_devmap_add_entry(0x70000000, 0x00100000);
@@ -101,3 +93,12 @@ u_int imx_soc_type()
return (IMXSOC_51);
}
+static platform_method_t imx51_methods[] = {
+ PLATFORMMETHOD(platform_attach, imx51_attach),
+ PLATFORMMETHOD(platform_devmap_init, imx51_devmap_init),
+ PLATFORMMETHOD(platform_lastaddr, imx51_lastaddr),
+
+ PLATFORMMETHOD_END,
+};
+
+FDT_PLATFORM_DEF(imx51, "i.MX51", 0, "fsl,imx51");
diff --git a/sys/arm/freescale/imx/imx53_machdep.c b/sys/arm/freescale/imx/imx53_machdep.c
index ebf09d9..92b59e4 100644
--- a/sys/arm/freescale/imx/imx53_machdep.c
+++ b/sys/arm/freescale/imx/imx53_machdep.c
@@ -39,36 +39,28 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/devmap.h>
#include <machine/machdep.h>
-#include <machine/platform.h>
+#include <machine/platformvar.h>
#include <arm/freescale/imx/imx_machdep.h>
-vm_offset_t
-platform_lastaddr(void)
+#include "platform_if.h"
+
+static vm_offset_t
+imx53_lastaddr(platform_t plat)
{
return (arm_devmap_lastaddr());
}
-void
-platform_probe_and_attach(void)
+static int
+imx53_attach(platform_t plat)
{
/* XXX - Get rid of this stuff soon. */
boothowto |= RB_VERBOSE|RB_MULTIPLE;
bootverbose = 1;
-}
-
-void
-platform_gpio_init(void)
-{
-
-}
-
-void
-platform_late_init(void)
-{
+ return (0);
}
/*
@@ -78,8 +70,8 @@ platform_late_init(void)
*
* Notably missing are entries for GPU, IPU, in general anything video related.
*/
-int
-platform_devmap_init(void)
+static int
+imx53_devmap_init(platform_t plat)
{
arm_devmap_add_entry(0x50000000, 0x00100000);
@@ -101,4 +93,13 @@ u_int imx_soc_type()
return (IMXSOC_53);
}
+static platform_method_t imx53_methods[] = {
+ PLATFORMMETHOD(platform_attach, imx53_attach),
+ PLATFORMMETHOD(platform_devmap_init, imx53_devmap_init),
+ PLATFORMMETHOD(platform_lastaddr, imx53_lastaddr),
+
+ PLATFORMMETHOD_END,
+};
+
+FDT_PLATFORM_DEF(imx53, "i.MX53", 0, "fsl,imx53");
diff --git a/sys/arm/freescale/imx/imx6_machdep.c b/sys/arm/freescale/imx/imx6_machdep.c
index 510a09b..2322cff 100644
--- a/sys/arm/freescale/imx/imx6_machdep.c
+++ b/sys/arm/freescale/imx/imx6_machdep.c
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#include <machine/devmap.h>
#include <machine/intr.h>
#include <machine/machdep.h>
-#include <machine/platform.h>
+#include <machine/platformvar.h>
#include <arm/arm/mpcore_timervar.h>
#include <arm/freescale/imx/imx6_anatopreg.h>
@@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$");
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
+#include "platform_if.h"
+
struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
@@ -90,29 +92,25 @@ fdt_pic_decode_t fdt_pic_table[] = {
NULL
};
-vm_offset_t
-platform_lastaddr(void)
+static vm_offset_t
+imx6_lastaddr(platform_t plat)
{
return (arm_devmap_lastaddr());
}
-void
-platform_probe_and_attach(void)
+static int
+imx6_attach(platform_t plat)
{
/* Inform the MPCore timer driver that its clock is variable. */
arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES);
-}
-
-void
-platform_gpio_init(void)
-{
+ return (0);
}
-void
-platform_late_init(void)
+static void
+imx6_late_init(platform_t plat)
{
/* Cache the gpio1 node handle for imx6_decode_fdt() workaround code. */
@@ -136,8 +134,8 @@ platform_late_init(void)
* static map some of that area. Be careful with other things in that area such
* as OCRAM that probably shouldn't be mapped as PTE_DEVICE memory.
*/
-int
-platform_devmap_init(void)
+static int
+imx6_devmap_init(platform_t plat)
{
const uint32_t IMX6_ARMMP_PHYS = 0x00a00000;
const uint32_t IMX6_ARMMP_SIZE = 0x00100000;
@@ -271,3 +269,15 @@ imx6_early_putc(int c)
early_putc_t *early_putc = imx6_early_putc;
#endif
+static platform_method_t imx6_methods[] = {
+ PLATFORMMETHOD(platform_attach, imx6_attach),
+ PLATFORMMETHOD(platform_lastaddr, imx6_lastaddr),
+ PLATFORMMETHOD(platform_devmap_init, imx6_devmap_init),
+ PLATFORMMETHOD(platform_late_init, imx6_late_init),
+
+ PLATFORMMETHOD_END,
+};
+
+FDT_PLATFORM_DEF2(imx6, imx6s, "i.MX6 Solo", 0, "fsl,imx6s");
+FDT_PLATFORM_DEF2(imx6, imx6d, "i.MX6 Dual", 0, "fsl,imx6d");
+FDT_PLATFORM_DEF2(imx6, imx6q, "i.MX6 Quad", 0, "fsl,imx6q");
diff --git a/sys/arm/freescale/imx/std.imx51 b/sys/arm/freescale/imx/std.imx51
index ce9d7d2..4ffcac7 100644
--- a/sys/arm/freescale/imx/std.imx51
+++ b/sys/arm/freescale/imx/std.imx51
@@ -1,6 +1,7 @@
# $FreeBSD$
machine arm armv6
cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoptions ARM_LITTLE_ENDIAN
options ARM_L2_PIPT
diff --git a/sys/arm/freescale/imx/std.imx53 b/sys/arm/freescale/imx/std.imx53
index 09bdb2d..6bc96cf 100644
--- a/sys/arm/freescale/imx/std.imx53
+++ b/sys/arm/freescale/imx/std.imx53
@@ -1,6 +1,7 @@
# $FreeBSD$
machine arm armv6
cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoptions ARM_LITTLE_ENDIAN
options ARM_L2_PIPT
diff --git a/sys/arm/freescale/imx/std.imx6 b/sys/arm/freescale/imx/std.imx6
index a559f17..4249f9e 100644
--- a/sys/arm/freescale/imx/std.imx6
+++ b/sys/arm/freescale/imx/std.imx6
@@ -1,6 +1,7 @@
# $FreeBSD$
machine arm armv6
cpu CPU_CORTEXA
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoptions ARM_LITTLE_ENDIAN
options ARM_L2_PIPT
diff --git a/sys/arm/freescale/vybrid/std.vybrid b/sys/arm/freescale/vybrid/std.vybrid
index 2fbd85c..35a2a25 100644
--- a/sys/arm/freescale/vybrid/std.vybrid
+++ b/sys/arm/freescale/vybrid/std.vybrid
@@ -4,6 +4,7 @@ makeoption ARM_LITTLE_ENDIAN
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
options PHYSADDR=0x80000000
diff --git a/sys/arm/include/asm.h b/sys/arm/include/asm.h
index 73b7355..9122e6e 100644
--- a/sys/arm/include/asm.h
+++ b/sys/arm/include/asm.h
@@ -39,6 +39,8 @@
#ifndef _MACHINE_ASM_H_
#define _MACHINE_ASM_H_
#include <sys/cdefs.h>
+#include <machine/acle-compat.h>
+#include <machine/sysreg.h>
#define _C_LABEL(x) x
#define _ASM_LABEL(x) x
@@ -58,7 +60,24 @@
#endif
/*
+ * gas/arm uses @ as a single comment character and thus cannot be used here.
+ * It recognises the # instead of an @ symbol in .type directives.
+ */
+#define _ASM_TYPE_FUNCTION #function
+#define _ASM_TYPE_OBJECT #object
+
+/* XXX Is this still the right prologue for profiling? */
+#ifdef GPROF
+#define _PROF_PROLOGUE \
+ mov ip, lr; \
+ bl __mcount
+#else
+#define _PROF_PROLOGUE
+#endif
+
+/*
* EENTRY()/EEND() mark "extra" entry/exit points from a function.
+ * LEENTRY()/LEEND() are the the same for local symbols.
* The unwind info cannot handle the concept of a nested function, or a function
* with multiple .fnstart directives, but some of our assembler code is written
* with multiple labels to allow entry at several points. The EENTRY() macro
@@ -66,41 +85,36 @@
* basically just a label that you can jump to. The EEND() macro does nothing
* at all, except document the exit point associated with the same-named entry.
*/
-#define _EENTRY(x) .globl x; .type x,_ASM_TYPE_FUNCTION; x:
-#define _EEND(x) /* nothing */
+#define GLOBAL(x) .global x
-/*
- * gas/arm uses @ as a single comment character and thus cannot be used here
- * Instead it recognised the # instead of an @ symbols in .type directives
- * We define a couple of macros so that assembly code will not be dependent
- * on one or the other.
- */
-#define _ASM_TYPE_FUNCTION #function
-#define _ASM_TYPE_OBJECT #object
-#define GLOBAL(X) .globl x
-#define _ENTRY(x) \
- .text; _ALIGN_TEXT; _EENTRY(x) _FNSTART
-#define _END(x) .size x, . - x; _FNEND
+#define _LEENTRY(x) .type x,_ASM_TYPE_FUNCTION; x:
+#define _LEEND(x) /* nothing */
+#define _EENTRY(x) GLOBAL(x); _LEENTRY(x)
+#define _EEND(x) _LEEND(x)
-#ifdef GPROF
-# define _PROF_PROLOGUE \
- mov ip, lr; bl __mcount
-#else
-# define _PROF_PROLOGUE
-#endif
+#define _LENTRY(x) .text; _ALIGN_TEXT; _LEENTRY(x); _FNSTART
+#define _LEND(x) .size x, . - x; _FNEND
+#define _ENTRY(x) .text; _ALIGN_TEXT; _EENTRY(x); _FNSTART
+#define _END(x) _LEND(x)
#define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
-#define EENTRY(y) _EENTRY(_C_LABEL(y)); _PROF_PROLOGUE
+#define EENTRY(y) _EENTRY(_C_LABEL(y));
#define ENTRY_NP(y) _ENTRY(_C_LABEL(y))
#define EENTRY_NP(y) _EENTRY(_C_LABEL(y))
#define END(y) _END(_C_LABEL(y))
-#define EEND(y)
+#define EEND(y) _EEND(_C_LABEL(y))
#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
-#define ASEENTRY(y) _EENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+#define ASLENTRY(y) _LENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+#define ASEENTRY(y) _EENTRY(_ASM_LABEL(y));
+#define ASLEENTRY(y) _LEENTRY(_ASM_LABEL(y));
#define ASENTRY_NP(y) _ENTRY(_ASM_LABEL(y))
+#define ASLENTRY_NP(y) _LENTRY(_ASM_LABEL(y))
#define ASEENTRY_NP(y) _EENTRY(_ASM_LABEL(y))
+#define ASLEENTRY_NP(y) _LEENTRY(_ASM_LABEL(y))
#define ASEND(y) _END(_ASM_LABEL(y))
-#define ASEEND(y)
+#define ASLEND(y) _LEND(_ASM_LABEL(y))
+#define ASEEND(y) _EEND(_ASM_LABEL(y))
+#define ASLEEND(y) _LEEND(_ASM_LABEL(y))
#define ASMSTR .asciz
@@ -209,4 +223,18 @@
# define RETc(c) mov##c pc, lr
#endif
+#if __ARM_ARCH >= 7
+#define ISB isb
+#define DSB dsb
+#define DMB dmb
+#elif __ARM_ARCH == 6
+#define ISB mcr CP15_CP15ISB
+#define DSB mcr CP15_CP15DSB
+#define DMB mcr CP15_CP15DMB
+#else
+#define ISB mcr CP15_CP15ISB
+#define DSB mcr CP15_CP15DSB /* DSB and DMB are the */
+#define DMB mcr CP15_CP15DSB /* same prior to v6.*/
+#endif
+
#endif /* !_MACHINE_ASM_H_ */
diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h
index da35e57..fb02153 100644
--- a/sys/arm/include/cpuconf.h
+++ b/sys/arm/include/cpuconf.h
@@ -99,6 +99,29 @@
#endif
#define ARM_NARCH (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 | ARM_ARCH_7A)
+
+/*
+ * Compatibility for userland builds that have no CPUTYPE defined. Use the ARCH
+ * constants predefined by the compiler to define our old-school arch constants.
+ * This is a stopgap measure to tide us over until the conversion of all code
+ * to the newer ACLE constants defined by ARM (see acle-compat.h).
+ */
+#if ARM_NARCH == 0
+#if defined(__ARM_ARCH_4T__)
+#undef ARM_ARCH_4
+#undef ARM_NARCH
+#define ARM_ARCH_4 1
+#define ARM_NARCH 1
+#define CPU_ARM9 1
+#elif defined(__ARM_ARCH_6ZK__)
+#undef ARM_ARCH_6
+#undef ARM_NARCH
+#define ARM_ARCH_6 1
+#define ARM_NARCH 1
+#define CPU_ARM1176 1
+#endif
+#endif
+
#if ARM_NARCH == 0 && !defined(KLD_MODULE) && defined(_KERNEL)
#error ARM_NARCH is 0
#endif
diff --git a/sys/arm/include/db_machdep.h b/sys/arm/include/db_machdep.h
index da3b30e..741cae9 100644
--- a/sys/arm/include/db_machdep.h
+++ b/sys/arm/include/db_machdep.h
@@ -38,7 +38,7 @@
typedef vm_offset_t db_addr_t;
typedef int db_expr_t;
-#define PC_REGS() ((db_addr_t)kdb_thrctx->un_32.pcb32_pc)
+#define PC_REGS() ((db_addr_t)kdb_thrctx->pcb_regs.sf_pc)
#define BKPT_INST (KERNEL_BREAKPOINT)
#define BKPT_SIZE (INSN_SIZE)
diff --git a/sys/arm/include/frame.h b/sys/arm/include/frame.h
index 1e6f43a..7655d89 100644
--- a/sys/arm/include/frame.h
+++ b/sys/arm/include/frame.h
@@ -86,57 +86,16 @@ struct trapframe {
#define tf_r13 tf_usr_sp
#define tf_r14 tf_usr_lr
#define tf_r15 tf_pc
-/*
- * * Scheduler activations upcall frame. Pushed onto user stack before
- * * calling an SA upcall.
- * */
-
-struct saframe {
-#if 0 /* in registers on entry to upcall */
- int sa_type;
- struct sa_t ** sa_sas;
- int sa_events;
- int sa_interrupted;
-#endif
- void * sa_arg;
-};
/*
- * * Signal frame. Pushed onto user stack before calling sigcode.
- * */
-
-/* the pointers are use in the trampoline code to locate the ucontext */
+ * Signal frame. Pushed onto user stack before calling sigcode.
+ * The pointers are used in the trampoline code to locate the ucontext.
+ */
struct sigframe {
- siginfo_t sf_si; /* actual saved siginfo */
+ siginfo_t sf_si; /* actual saved siginfo */
ucontext_t sf_uc; /* actual saved ucontext */
};
-/*
- * System stack frames.
- */
-
-
-typedef struct irqframe {
- unsigned int if_spsr;
- unsigned int if_r0;
- unsigned int if_r1;
- unsigned int if_r2;
- unsigned int if_r3;
- unsigned int if_r4;
- unsigned int if_r5;
- unsigned int if_r6;
- unsigned int if_r7;
- unsigned int if_r8;
- unsigned int if_r9;
- unsigned int if_r10;
- unsigned int if_r11;
- unsigned int if_r12;
- unsigned int if_usr_sp;
- unsigned int if_usr_lr;
- unsigned int if_svc_sp;
- unsigned int if_svc_lr;
- unsigned int if_pc;
-} irqframe_t;
/*
* Switch frame.
@@ -144,16 +103,23 @@ typedef struct irqframe {
* It is important this is a multiple of 8 bytes so the stack is correctly
* aligned when we create new threads.
*/
-
-struct switchframe {
- u_int pad; /* Used to pad the struct to a multiple of 8-bytes */
- u_int sf_r4;
- u_int sf_r5;
- u_int sf_r6;
- u_int sf_r7;
- u_int sf_pc;
+struct switchframe
+{
+ register_t sf_r4;
+ register_t sf_r5;
+ register_t sf_r6;
+ register_t sf_r7;
+ register_t sf_r8;
+ register_t sf_r9;
+ register_t sf_r10;
+ register_t sf_r11;
+ register_t sf_r12;
+ register_t sf_sp;
+ register_t sf_lr;
+ register_t sf_pc;
};
+
/*
* Stack frame. Used during stack traces (db_trace.c)
*/
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 3509772..9ee86f3 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -39,6 +39,10 @@
#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#endif
+
/* XXX move to std.* files? */
#ifdef CPU_XSCALE_81342
#define NIRQ 128
@@ -85,4 +89,8 @@ void gic_init_secondary(void);
int gic_decode_fdt(uint32_t iparentnode, uint32_t *intrcells, int *interrupt,
int *trig, int *pol);
+#ifdef FDT
+int arm_fdt_map_irq(phandle_t, pcell_t *, int);
+#endif
+
#endif /* _MACHINE_INTR_H */
diff --git a/sys/arm/include/machdep.h b/sys/arm/include/machdep.h
index 907270e..ee524a8 100644
--- a/sys/arm/include/machdep.h
+++ b/sys/arm/include/machdep.h
@@ -20,8 +20,7 @@ struct trapframe;
void arm_lock_cache_line(vm_offset_t);
void init_proc0(vm_offset_t kstack);
void halt(void);
-void data_abort_handler(struct trapframe *);
-void prefetch_abort_handler(struct trapframe *);
+void abort_handler(struct trapframe *, int );
void set_stackptrs(int cpu);
void undefinedinstruction_bounce(struct trapframe *);
diff --git a/sys/arm/include/pcb.h b/sys/arm/include/pcb.h
index 252d94e..b5ed607 100644
--- a/sys/arm/include/pcb.h
+++ b/sys/arm/include/pcb.h
@@ -39,50 +39,29 @@
#define _MACHINE_PCB_H_
#include <machine/fp.h>
+#include <machine/frame.h>
-struct trapframe;
-
-struct pcb_arm32 {
- vm_offset_t pcb32_pagedir; /* PT hooks */
- uint32_t *pcb32_pl1vec; /* PTR to vector_base L1 entry*/
- uint32_t pcb32_l1vec; /* Value to stuff on ctx sw */
- u_int pcb32_dacr; /* Domain Access Control Reg */
- /*
- * WARNING!
- * cpuswitch.S relies on pcb32_r8 being quad-aligned in struct pcb
- * (due to the use of "strd" when compiled for XSCALE)
- */
- u_int pcb32_r8; /* used */
- u_int pcb32_r9; /* used */
- u_int pcb32_r10; /* used */
- u_int pcb32_r11; /* used */
- u_int pcb32_r12; /* used */
- u_int pcb32_sp; /* used */
- u_int pcb32_lr;
- u_int pcb32_pc;
-};
-#define pcb_pagedir un_32.pcb32_pagedir
-#define pcb_pl1vec un_32.pcb32_pl1vec
-#define pcb_l1vec un_32.pcb32_l1vec
-#define pcb_dacr un_32.pcb32_dacr
-#define pcb_cstate un_32.pcb32_cstate
-
/*
* WARNING!
- * See warning for struct pcb_arm32, above, before changing struct pcb!
+ * Keep pcb_regs first for faster access in switch.S
*/
struct pcb {
+ struct switchframe pcb_regs; /* CPU state */
u_int pcb_flags;
#define PCB_OWNFPU 0x00000001
#define PCB_NOALIGNFLT 0x00000002
caddr_t pcb_onfault; /* On fault handler */
- struct pcb_arm32 un_32;
+ vm_offset_t pcb_pagedir; /* PT hooks */
+ uint32_t *pcb_pl1vec; /* PTR to vector_base L1 entry*/
+ uint32_t pcb_l1vec; /* Value to stuff on ctx sw */
+ u_int pcb_dacr; /* Domain Access Control Reg */
+
struct vfp_state pcb_vfpstate; /* VP/NEON state */
u_int pcb_vfpcpu; /* VP/NEON last cpu */
} __aligned(8); /*
* We need the PCB to be aligned on 8 bytes, as we may
- * access it using ldrd/strd, and some CPUs require it
+ * access it using ldrd/strd, and ARM ABI require it
* to by aligned on 8 bytes.
*/
diff --git a/sys/arm/include/smp.h b/sys/arm/include/smp.h
index 6301c9a..3803674 100644
--- a/sys/arm/include/smp.h
+++ b/sys/arm/include/smp.h
@@ -24,7 +24,7 @@ void ipi_selected(cpuset_t cpus, u_int ipi);
/* PIC interface */
void pic_ipi_send(cpuset_t cpus, u_int ipi);
void pic_ipi_clear(int ipi);
-int pic_ipi_get(int arg);
+int pic_ipi_read(int arg);
/* Platform interface */
void platform_mp_setmaxid(void);
diff --git a/sys/arm/include/sysreg.h b/sys/arm/include/sysreg.h
index 76b1f2b..b1c7fd3 100644
--- a/sys/arm/include/sysreg.h
+++ b/sys/arm/include/sysreg.h
@@ -99,12 +99,13 @@
#if __ARM_ARCH >= 6
/* From ARMv6: */
#define CP15_IFSR(rr) p15, 0, rr, c5, c0, 1 /* Instruction Fault Status Register */
+#endif
+#if __ARM_ARCH >= 7
/* From ARMv7: */
#define CP15_ADFSR(rr) p15, 0, rr, c5, c1, 0 /* Auxiliary Data Fault Status Register */
#define CP15_AIFSR(rr) p15, 0, rr, c5, c1, 1 /* Auxiliary Instruction Fault Status Register */
#endif
-
/*
* CP15 C6 registers
*/
@@ -118,7 +119,7 @@
/*
* CP15 C7 registers
*/
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH >= 7 && defined(SMP)
/* From ARMv7: */
#define CP15_ICIALLUIS p15, 0, r0, c7, c1, 0 /* Instruction cache invalidate all PoU, IS */
#define CP15_BPIALLIS p15, 0, r0, c7, c1, 6 /* Branch predictor invalidate all IS */
@@ -128,14 +129,14 @@
#define CP15_ICIALLU p15, 0, r0, c7, c5, 0 /* Instruction cache invalidate all PoU */
#define CP15_ICIMVAU(rr) p15, 0, rr, c7, c5, 1 /* Instruction cache invalidate */
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH == 6
/* Deprecated in ARMv7 */
#define CP15_CP15ISB p15, 0, r0, c7, c5, 4 /* ISB */
#endif
#define CP15_BPIALL p15, 0, r0, c7, c5, 6 /* Branch predictor invalidate all */
#define CP15_BPIMVA p15, 0, rr, c7, c5, 7 /* Branch predictor invalidate by MVA */
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH == 6
/* Only ARMv6: */
#define CP15_DCIALL p15, 0, r0, c7, c6, 0 /* Data cache invalidate all */
#endif
@@ -147,7 +148,7 @@
#define CP15_ATS1CUR(rr) p15, 0, rr, c7, c8, 2 /* Stage 1 Current state unprivileged read */
#define CP15_ATS1CUW(rr) p15, 0, rr, c7, c8, 3 /* Stage 1 Current state unprivileged write */
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH >= 7
/* From ARMv7: */
#define CP15_ATS12NSOPR(rr) p15, 0, rr, c7, c8, 4 /* Stages 1 and 2 Non-secure only PL1 read */
#define CP15_ATS12NSOPW(rr) p15, 0, rr, c7, c8, 5 /* Stages 1 and 2 Non-secure only PL1 write */
@@ -155,24 +156,24 @@
#define CP15_ATS12NSOUW(rr) p15, 0, rr, c7, c8, 7 /* Stages 1 and 2 Non-secure only unprivileged write */
#endif
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH == 6
/* Only ARMv6: */
#define CP15_DCCALL p15, 0, r0, c7, c10, 0 /* Data cache clean all */
#endif
#define CP15_DCCMVAC(rr) p15, 0, rr, c7, c10, 1 /* Data cache clean by MVA PoC */
#define CP15_DCCSW(rr) p15, 0, rr, c7, c10, 2 /* Data cache clean by set/way */
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH == 6
/* Only ARMv6: */
#define CP15_CP15DSB p15, 0, r0, c7, c10, 4 /* DSB */
#define CP15_CP15DMB p15, 0, r0, c7, c10, 5 /* DMB */
#endif
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH >= 7
/* From ARMv7: */
#define CP15_DCCMVAU(rr) p15, 0, rr, c7, c11, 1 /* Data cache clean by MVA PoU */
#endif
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH == 6
/* Only ARMv6: */
#define CP15_DCCIALL p15, 0, r0, c7, c14, 0 /* Data cache clean and invalidate all */
#endif
@@ -182,7 +183,7 @@
/*
* CP15 C8 registers
*/
-#if __ARM_ARCH >= 6
+#if __ARM_ARCH >= 7 && defined(SMP)
/* From ARMv7: */
#define CP15_TLBIALLIS p15, 0, r0, c8, c3, 0 /* Invalidate entire unified TLB IS */
#define CP15_TLBIMVAIS(rr) p15, 0, rr, c8, c3, 1 /* Invalidate unified TLB by MVA IS */
@@ -229,4 +230,9 @@
#define CP15_TPIDRURO(rr) p15, 0, rr, c13, c0, 3 /* User Read-Only Thread ID Register */
#define CP15_TPIDRPRW(rr) p15, 0, rr, c13, c0, 4 /* PL1 only Thread ID Register */
+/*
+ * CP15 C15 registers
+ */
+#define CP15_CBAR(rr) p15, 4, rr, c15, c0, 0 /* Configuration Base Address Register */
+
#endif /* !MACHINE_SYSREG_H */
diff --git a/sys/arm/lpc/lpc_intc.c b/sys/arm/lpc/lpc_intc.c
index 3137e89..bf26645 100644
--- a/sys/arm/lpc/lpc_intc.c
+++ b/sys/arm/lpc/lpc_intc.c
@@ -59,10 +59,10 @@ static void lpc_intc_eoi(void *);
static struct lpc_intc_softc *intc_softc = NULL;
-#define intc_read_4(reg) \
- bus_space_read_4(intc_softc->li_bst, intc_softc->li_bsh, reg)
-#define intc_write_4(reg, val) \
- bus_space_write_4(intc_softc->li_bst, intc_softc->li_bsh, reg, val)
+#define intc_read_4(_sc, _reg) \
+ bus_space_read_4((_sc)->li_bst, (_sc)->li_bsh, (_reg))
+#define intc_write_4(_sc, _reg, _val) \
+ bus_space_write_4((_sc)->li_bst, (_sc)->li_bsh, (_reg), (_val))
static int
lpc_intc_probe(device_t dev)
@@ -100,12 +100,12 @@ lpc_intc_attach(device_t dev)
arm_post_filter = lpc_intc_eoi;
/* Clear interrupt status registers and disable all interrupts */
- intc_write_4(LPC_INTC_MIC_ER, 0);
- intc_write_4(LPC_INTC_SIC1_ER, 0);
- intc_write_4(LPC_INTC_SIC2_ER, 0);
- intc_write_4(LPC_INTC_MIC_RSR, ~0);
- intc_write_4(LPC_INTC_SIC1_RSR, ~0);
- intc_write_4(LPC_INTC_SIC2_RSR, ~0);
+ intc_write_4(sc, LPC_INTC_MIC_ER, 0);
+ intc_write_4(sc, LPC_INTC_SIC1_ER, 0);
+ intc_write_4(sc, LPC_INTC_SIC2_ER, 0);
+ intc_write_4(sc, LPC_INTC_MIC_RSR, ~0);
+ intc_write_4(sc, LPC_INTC_SIC1_RSR, ~0);
+ intc_write_4(sc, LPC_INTC_SIC2_RSR, ~0);
return (0);
}
@@ -128,25 +128,26 @@ DRIVER_MODULE(pic, simplebus, lpc_intc_driver, lpc_intc_devclass, 0, 0);
int
arm_get_next_irq(int last)
{
+ struct lpc_intc_softc *sc = intc_softc;
uint32_t value;
int i;
/* IRQs 0-31 are mapped to LPC_INTC_MIC_SR */
- value = intc_read_4(LPC_INTC_MIC_SR);
+ value = intc_read_4(sc, LPC_INTC_MIC_SR);
for (i = 0; i < 32; i++) {
if (value & (1 << i))
return (i);
}
/* IRQs 32-63 are mapped to LPC_INTC_SIC1_SR */
- value = intc_read_4(LPC_INTC_SIC1_SR);
+ value = intc_read_4(sc, LPC_INTC_SIC1_SR);
for (i = 0; i < 32; i++) {
if (value & (1 << i))
return (i + 32);
}
/* IRQs 64-95 are mapped to LPC_INTC_SIC2_SR */
- value = intc_read_4(LPC_INTC_SIC2_SR);
+ value = intc_read_4(sc, LPC_INTC_SIC2_SR);
for (i = 0; i < 32; i++) {
if (value & (1 << i))
return (i + 64);
@@ -158,6 +159,7 @@ arm_get_next_irq(int last)
void
arm_mask_irq(uintptr_t nb)
{
+ struct lpc_intc_softc *sc = intc_softc;
int reg;
uint32_t value;
@@ -174,14 +176,15 @@ arm_mask_irq(uintptr_t nb)
reg = LPC_INTC_MIC_ER;
/* Clear bit in ER register */
- value = intc_read_4(reg);
+ value = intc_read_4(sc, reg);
value &= ~(1 << nb);
- intc_write_4(reg, value);
+ intc_write_4(sc, reg, value);
}
void
arm_unmask_irq(uintptr_t nb)
{
+ struct lpc_intc_softc *sc = intc_softc;
int reg;
uint32_t value;
@@ -195,14 +198,15 @@ arm_unmask_irq(uintptr_t nb)
reg = LPC_INTC_MIC_ER;
/* Set bit in ER register */
- value = intc_read_4(reg);
+ value = intc_read_4(sc, reg);
value |= (1 << nb);
- intc_write_4(reg, value);
+ intc_write_4(sc, reg, value);
}
static void
lpc_intc_eoi(void *data)
{
+ struct lpc_intc_softc *sc = intc_softc;
int reg;
int nb = (int)data;
uint32_t value;
@@ -217,9 +221,9 @@ lpc_intc_eoi(void *data)
reg = LPC_INTC_MIC_RSR;
/* Set bit in RSR register */
- value = intc_read_4(reg);
+ value = intc_read_4(sc, reg);
value |= (1 << nb);
- intc_write_4(reg, value);
+ intc_write_4(sc, reg, value);
}
diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c
index 813caf4..bfb5554 100644
--- a/sys/arm/mv/mpic.c
+++ b/sys/arm/mv/mpic.c
@@ -375,7 +375,7 @@ pic_ipi_send(cpuset_t cpus, u_int ipi)
}
int
-pic_ipi_get(int i __unused)
+pic_ipi_read(int i __unused)
{
uint32_t val;
diff --git a/sys/arm/mv/std-pj4b.mv b/sys/arm/mv/std-pj4b.mv
index 7d779c2..1053ff0 100644
--- a/sys/arm/mv/std-pj4b.mv
+++ b/sys/arm/mv/std-pj4b.mv
@@ -3,5 +3,6 @@
files "../mv/files.mv"
cpu CPU_MV_PJ4B
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
options VM_MAXUSER_ADDRESS="(KERNBASE-(1024*1024*1024))"
diff --git a/sys/arm/rockchip/std.rk30xx b/sys/arm/rockchip/std.rk30xx
index 79ddcc6..b62b77a 100644
--- a/sys/arm/rockchip/std.rk30xx
+++ b/sys/arm/rockchip/std.rk30xx
@@ -3,6 +3,7 @@
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
makeoption ARM_LITTLE_ENDIAN
# Physical memory starts at 0x60400000. We assume images are loaded at
diff --git a/sys/arm/samsung/exynos/std.exynos5250 b/sys/arm/samsung/exynos/std.exynos5250
index 5f59adc..39c378b 100644
--- a/sys/arm/samsung/exynos/std.exynos5250
+++ b/sys/arm/samsung/exynos/std.exynos5250
@@ -4,6 +4,7 @@ makeoption ARM_LITTLE_ENDIAN
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
options PHYSADDR=0x40000000
diff --git a/sys/arm/samsung/exynos/std.exynos5420 b/sys/arm/samsung/exynos/std.exynos5420
index c6468e7..b70537d 100644
--- a/sys/arm/samsung/exynos/std.exynos5420
+++ b/sys/arm/samsung/exynos/std.exynos5420
@@ -4,6 +4,7 @@ makeoption ARM_LITTLE_ENDIAN
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
options PHYSADDR=0x20000000
diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c
index 213a1d3..675a5f3 100644
--- a/sys/arm/ti/aintc.c
+++ b/sys/arm/ti/aintc.c
@@ -72,10 +72,10 @@ static struct resource_spec ti_aintc_spec[] = {
static struct ti_aintc_softc *ti_aintc_sc = NULL;
-#define aintc_read_4(reg) \
- bus_space_read_4(ti_aintc_sc->aintc_bst, ti_aintc_sc->aintc_bsh, reg)
-#define aintc_write_4(reg, val) \
- bus_space_write_4(ti_aintc_sc->aintc_bst, ti_aintc_sc->aintc_bsh, reg, val)
+#define aintc_read_4(_sc, reg) \
+ bus_space_read_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg))
+#define aintc_write_4(_sc, reg, val) \
+ bus_space_write_4((_sc)->aintc_bst, (_sc)->aintc_bsh, (reg), (val))
static int
@@ -112,17 +112,17 @@ ti_aintc_attach(device_t dev)
ti_aintc_sc = sc;
- x = aintc_read_4(INTC_REVISION);
+ x = aintc_read_4(sc, INTC_REVISION);
device_printf(dev, "Revision %u.%u\n",(x >> 4) & 0xF, x & 0xF);
/* SoftReset */
- aintc_write_4(INTC_SYSCONFIG, 2);
+ aintc_write_4(sc, INTC_SYSCONFIG, 2);
/* Wait for reset to complete */
- while(!(aintc_read_4(INTC_SYSSTATUS) & 1));
+ while(!(aintc_read_4(sc, INTC_SYSSTATUS) & 1));
/*Set Priority Threshold */
- aintc_write_4(INTC_THRESHOLD, 0xFF);
+ aintc_write_4(sc, INTC_THRESHOLD, 0xFF);
return (0);
}
@@ -146,22 +146,23 @@ DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass, 0, 0);
int
arm_get_next_irq(int last_irq)
{
+ struct ti_aintc_softc *sc = ti_aintc_sc;
uint32_t active_irq;
if (last_irq != -1) {
- aintc_write_4(INTC_ISR_CLEAR(last_irq >> 5),
+ aintc_write_4(sc, INTC_ISR_CLEAR(last_irq >> 5),
1UL << (last_irq & 0x1F));
- aintc_write_4(INTC_CONTROL,1);
+ aintc_write_4(sc, INTC_CONTROL, 1);
}
/* Get the next active interrupt */
- active_irq = aintc_read_4(INTC_SIR_IRQ);
+ active_irq = aintc_read_4(sc, INTC_SIR_IRQ);
/* Check for spurious interrupt */
if ((active_irq & 0xffffff80)) {
- device_printf(ti_aintc_sc->sc_dev,
- "Spurious interrupt detected (0x%08x)\n", active_irq);
- aintc_write_4(INTC_SIR_IRQ, 0);
+ device_printf(sc->sc_dev,
+ "Spurious interrupt detected (0x%08x)\n", active_irq);
+ aintc_write_4(sc, INTC_SIR_IRQ, 0);
return -1;
}
@@ -174,13 +175,16 @@ arm_get_next_irq(int last_irq)
void
arm_mask_irq(uintptr_t nb)
{
- aintc_write_4(INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F)));
+ struct ti_aintc_softc *sc = ti_aintc_sc;
+
+ aintc_write_4(sc, INTC_MIR_SET(nb >> 5), (1UL << (nb & 0x1F)));
}
void
arm_unmask_irq(uintptr_t nb)
{
+ struct ti_aintc_softc *sc = ti_aintc_sc;
arm_irq_memory_barrier(nb);
- aintc_write_4(INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F)));
+ aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F)));
}
diff --git a/sys/arm/ti/am335x/am335x_usbss.c b/sys/arm/ti/am335x/am335x_usbss.c
index f1204f3..0173922 100644
--- a/sys/arm/ti/am335x/am335x_usbss.c
+++ b/sys/arm/ti/am335x/am335x_usbss.c
@@ -288,21 +288,30 @@ musbotg_attach(device_t dev)
return (ENXIO);
}
+ /* Enable device clocks. */
+ ti_prcm_clk_enable(MUSB0_CLK);
+
/*
- * Reset USBSS, USB0 and USB1
+ * Reset USBSS, USB0 and USB1.
+ * The registers of USB subsystem must not be accessed while the
+ * reset pulse is active (200ns).
*/
+ USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET);
+ DELAY(100);
+ i = 10;
+ while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) {
+ DELAY(100);
+ if (i-- == 0) {
+ device_printf(dev, "reset timeout.\n");
+ return (ENXIO);
+ }
+ }
+
+ /* Read the module revision. */
rev = USBSS_READ4(sc, USBSS_REVREG);
device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n",
(rev >> 8) & 7, (rev >> 6) & 3, rev & 63);
- ti_prcm_clk_enable(MUSB0_CLK);
-
- USBSS_WRITE4(sc, USBSS_SYSCONFIG,
- USBSS_SYSCONFIG_SRESET);
- while (USBSS_READ4(sc, USBSS_SYSCONFIG) &
- USBSS_SYSCONFIG_SRESET)
- ;
-
err = bus_setup_intr(dev, sc->sc_irq_res[0],
INTR_TYPE_BIO | INTR_MPSAFE,
NULL, (driver_intr_t *)musbotg_usbss_interrupt, sc,
diff --git a/sys/arm/ti/std.ti b/sys/arm/ti/std.ti
index 218d731..5e859b6 100644
--- a/sys/arm/ti/std.ti
+++ b/sys/arm/ti/std.ti
@@ -2,5 +2,6 @@
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
files "../ti/files.ti"
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index 612ceb9..5fe8094 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 2011
- * Ben Gray <ben.r.gray@gmail.com>.
+ * Copyright (c) 2011 Ben Gray <ben.r.gray@gmail.com>.
+ * Copyright (c) 2014 Luiz Otavio O Souza <loos@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,17 +26,8 @@
*/
/**
- * Very simple GPIO (general purpose IO) driver module for TI OMAP SoC's.
- *
- * Currently this driver only does the basics, get a value on a pin & set a
- * value on a pin. Hopefully over time I'll expand this to be a bit more generic
- * and support interrupts and other various bits on the SoC can do ... in the
- * meantime this is all you get.
- *
- * Beware the OMA datasheet(s) lists GPIO banks 1-6, whereas I've used 0-5 here
- * in the code.
- *
- *
+ * Beware that the OMAP4 datasheet(s) lists GPIO banks 1-6, whereas the code
+ * here uses 0-5.
*/
#include <sys/cdefs.h>
@@ -52,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/gpio.h>
+#include <sys/interrupt.h>
#include <machine/bus.h>
#include <machine/resource.h>
@@ -69,10 +61,13 @@ __FBSDID("$FreeBSD$");
#include "gpio_if.h"
#include "ti_gpio_if.h"
+#if !defined(SOC_OMAP4) && !defined(SOC_TI_AM335X)
+#error "Unknown SoC"
+#endif
+
/* Register definitions */
#define TI_GPIO_REVISION 0x0000
#define TI_GPIO_SYSCONFIG 0x0010
-#if defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
#define TI_GPIO_IRQSTATUS_RAW_0 0x0024
#define TI_GPIO_IRQSTATUS_RAW_1 0x0028
#define TI_GPIO_IRQSTATUS_0 0x002C
@@ -103,9 +98,6 @@ __FBSDID("$FreeBSD$");
#define TI_GPIO_SETWKUENA 0x0184
#define TI_GPIO_CLEARDATAOUT 0x0190
#define TI_GPIO_SETDATAOUT 0x0194
-#else
-#error "Unknown SoC"
-#endif
/* Other SoC Specific definitions */
#define OMAP4_MAX_GPIO_BANKS 6
@@ -117,6 +109,10 @@ __FBSDID("$FreeBSD$");
#define AM335X_INTR_PER_BANK 2
#define AM335X_GPIO_REV 0x50600801
#define PINS_PER_BANK 32
+#define TI_GPIO_BANK(p) ((p) / PINS_PER_BANK)
+#define TI_GPIO_MASK(p) (1U << ((p) % PINS_PER_BANK))
+
+static struct ti_gpio_softc *ti_gpio_sc = NULL;
static u_int
ti_max_gpio_banks(void)
@@ -226,17 +222,17 @@ static struct resource_spec ti_gpio_irq_spec[] = {
/**
* Macros for driver mutex locking
*/
-#define TI_GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
-#define TI_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define TI_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
+#define TI_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->sc_mtx)
#define TI_GPIO_LOCK_INIT(_sc) \
- mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
- "ti_gpio", MTX_DEF)
-#define TI_GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx)
-#define TI_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
-#define TI_GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
+ mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
+ "ti_gpio", MTX_SPIN)
+#define TI_GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
+#define TI_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+#define TI_GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
/**
- * ti_gpio_read_4 - reads a 16-bit value from one of the PADCONFS registers
+ * ti_gpio_read_4 - reads a 32-bit value from one of the GPIO registers
* @sc: GPIO device context
* @bank: The bank to read from
* @off: The offset of a register from the GPIO register address range
@@ -252,7 +248,7 @@ ti_gpio_read_4(struct ti_gpio_softc *sc, unsigned int bank, bus_size_t off)
}
/**
- * ti_gpio_write_4 - writes a 32-bit value to one of the PADCONFS registers
+ * ti_gpio_write_4 - writes a 32-bit value to one of the GPIO registers
* @sc: GPIO device context
* @bank: The bank to write to
* @off: The offset of a register from the GPIO register address range
@@ -273,13 +269,43 @@ ti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
{
/* We clear both set of registers. */
-#if defined(SOC_OMAP4) || defined(SOC_TI_AM335X)
ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_0, mask);
ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_CLR_1, mask);
-#else
- ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE1, mask);
- ti_gpio_write_4(sc, bank, TI_GPIO_CLEARIRQENABLE2, mask);
-#endif
+}
+
+static inline void
+ti_gpio_intr_set(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
+{
+
+ /*
+ * On OMAP4 we unmask only the MPU interrupt and on AM335x we
+ * also activate only the first interrupt.
+ */
+ ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_SET_0, mask);
+}
+
+static inline void
+ti_gpio_intr_ack(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
+{
+
+ /*
+ * Acknowledge the interrupt on both registers even if we use only
+ * the first one.
+ */
+ ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_0, mask);
+ ti_gpio_write_4(sc, bank, TI_GPIO_IRQSTATUS_1, mask);
+}
+
+static inline uint32_t
+ti_gpio_intr_status(struct ti_gpio_softc *sc, unsigned int bank)
+{
+ uint32_t reg;
+
+ /* Get the status from both registers. */
+ reg = ti_gpio_read_4(sc, bank, TI_GPIO_IRQSTATUS_0);
+ reg |= ti_gpio_read_4(sc, bank, TI_GPIO_IRQSTATUS_1);
+
+ return (reg);
}
/**
@@ -290,7 +316,7 @@ ti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
*
*
* LOCKING:
- * Internally locks the context
+ * No locking required, returns static data.
*
* RETURNS:
* Returns 0 on success otherwise an error code
@@ -298,23 +324,21 @@ ti_gpio_intr_clr(struct ti_gpio_softc *sc, unsigned int bank, uint32_t mask)
static int
ti_gpio_pin_max(device_t dev, int *maxpin)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- unsigned int i;
- unsigned int banks = 0;
- TI_GPIO_LOCK(sc);
+ *maxpin = ti_max_gpio_banks() * PINS_PER_BANK - 1;
- /* Calculate how many valid banks we have and then multiply that by 32 to
- * give use the total number of pins.
- */
- for (i = 0; i < ti_max_gpio_banks(); i++) {
- if (sc->sc_mem_res[i] != NULL)
- banks++;
- }
+ return (0);
+}
- *maxpin = (banks * PINS_PER_BANK) - 1;
+static int
+ti_gpio_valid_pin(struct ti_gpio_softc *sc, int pin)
+{
- TI_GPIO_UNLOCK(sc);
+ if (pin > sc->sc_maxpin ||
+ TI_GPIO_BANK(pin) >= ti_max_gpio_banks() ||
+ sc->sc_mem_res[TI_GPIO_BANK(pin)] == NULL) {
+ return (EINVAL);
+ }
return (0);
}
@@ -332,7 +356,7 @@ ti_gpio_pin_max(device_t dev, int *maxpin)
* - GPIO_PIN_PULLDOWN
*
* LOCKING:
- * Internally locks the context
+ * No locking required, returns static data.
*
* RETURNS:
* Returns 0 on success otherwise an error code
@@ -340,22 +364,15 @@ ti_gpio_pin_max(device_t dev, int *maxpin)
static int
ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
- *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |GPIO_PIN_PULLUP |
+ *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP |
GPIO_PIN_PULLDOWN);
- TI_GPIO_UNLOCK(sc);
-
return (0);
}
@@ -378,20 +395,15 @@ ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
static int
ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
/* Get the current pin state */
+ TI_GPIO_LOCK(sc);
TI_GPIO_GET_FLAGS(dev, pin, flags);
-
TI_GPIO_UNLOCK(sc);
return (0);
@@ -407,7 +419,7 @@ ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
* of the pin.
*
* LOCKING:
- * Internally locks the context
+ * No locking required, returns static data.
*
* RETURNS:
* Returns 0 on success otherwise an error code
@@ -415,23 +427,16 @@ ti_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
static int
ti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
/* Set a very simple name */
snprintf(name, GPIOMAXNAME, "gpio_%u", pin);
name[GPIOMAXNAME - 1] = '\0';
- TI_GPIO_UNLOCK(sc);
-
return (0);
}
@@ -457,33 +462,27 @@ ti_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
static int
ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
- uint32_t mask = (1UL << (pin % PINS_PER_BANK));
- uint32_t reg_val;
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
+ uint32_t oe;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
/* Set the GPIO mode and state */
+ TI_GPIO_LOCK(sc);
if (TI_GPIO_SET_FLAGS(dev, pin, flags) != 0) {
TI_GPIO_UNLOCK(sc);
return (EINVAL);
}
/* If configuring as an output set the "output enable" bit */
- reg_val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
+ oe = ti_gpio_read_4(sc, TI_GPIO_BANK(pin), TI_GPIO_OE);
if (flags & GPIO_PIN_INPUT)
- reg_val |= mask;
+ oe |= TI_GPIO_MASK(pin);
else
- reg_val &= ~mask;
- ti_gpio_write_4(sc, bank, TI_GPIO_OE, reg_val);
-
+ oe &= ~TI_GPIO_MASK(pin);
+ ti_gpio_write_4(sc, TI_GPIO_BANK(pin), TI_GPIO_OE, oe);
TI_GPIO_UNLOCK(sc);
return (0);
@@ -506,21 +505,19 @@ ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
static int
ti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
- uint32_t mask = (1UL << (pin % PINS_PER_BANK));
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
+ uint32_t reg;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
-
- ti_gpio_write_4(sc, bank, (value == GPIO_PIN_LOW) ? TI_GPIO_CLEARDATAOUT
- : TI_GPIO_SETDATAOUT, mask);
+ TI_GPIO_LOCK(sc);
+ if (value == GPIO_PIN_LOW)
+ reg = TI_GPIO_CLEARDATAOUT;
+ else
+ reg = TI_GPIO_SETDATAOUT;
+ ti_gpio_write_4(sc, TI_GPIO_BANK(pin), reg, TI_GPIO_MASK(pin));
TI_GPIO_UNLOCK(sc);
return (0);
@@ -544,28 +541,25 @@ ti_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
static int
ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
- uint32_t mask = (1UL << (pin % PINS_PER_BANK));
- uint32_t val = 0;
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
+ uint32_t oe, reg, val;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
-
- /* Sanity check the pin is not configured as an output */
- val = ti_gpio_read_4(sc, bank, TI_GPIO_OE);
- /* Read the value on the pin */
- if (val & mask)
- *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAIN) & mask) ? 1 : 0;
+ /*
+ * Return data from output latch when set as output and from the
+ * input register otherwise.
+ */
+ TI_GPIO_LOCK(sc);
+ oe = ti_gpio_read_4(sc, TI_GPIO_BANK(pin), TI_GPIO_OE);
+ if (oe & TI_GPIO_MASK(pin))
+ reg = TI_GPIO_DATAIN;
else
- *value = (ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT) & mask) ? 1 : 0;
-
+ reg = TI_GPIO_DATAOUT;
+ val = ti_gpio_read_4(sc, TI_GPIO_BANK(pin), reg);
+ *value = (val & TI_GPIO_MASK(pin)) ? 1 : 0;
TI_GPIO_UNLOCK(sc);
return (0);
@@ -586,26 +580,21 @@ ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
static int
ti_gpio_pin_toggle(device_t dev, uint32_t pin)
{
- struct ti_gpio_softc *sc = device_get_softc(dev);
- uint32_t bank = (pin / PINS_PER_BANK);
- uint32_t mask = (1UL << (pin % PINS_PER_BANK));
- uint32_t val;
-
- TI_GPIO_LOCK(sc);
+ struct ti_gpio_softc *sc;
+ uint32_t reg, val;
- /* Sanity check the pin number is valid */
- if ((bank >= ti_max_gpio_banks()) || (sc->sc_mem_res[bank] == NULL)) {
- TI_GPIO_UNLOCK(sc);
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
return (EINVAL);
- }
/* Toggle the pin */
- val = ti_gpio_read_4(sc, bank, TI_GPIO_DATAOUT);
- if (val & mask)
- ti_gpio_write_4(sc, bank, TI_GPIO_CLEARDATAOUT, mask);
+ TI_GPIO_LOCK(sc);
+ val = ti_gpio_read_4(sc, TI_GPIO_BANK(pin), TI_GPIO_DATAOUT);
+ if (val & TI_GPIO_MASK(pin))
+ reg = TI_GPIO_CLEARDATAOUT;
else
- ti_gpio_write_4(sc, bank, TI_GPIO_SETDATAOUT, mask);
-
+ reg = TI_GPIO_SETDATAOUT;
+ ti_gpio_write_4(sc, TI_GPIO_BANK(pin), reg, TI_GPIO_MASK(pin));
TI_GPIO_UNLOCK(sc);
return (0);
@@ -615,20 +604,40 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin)
* ti_gpio_intr - ISR for all GPIO modules
* @arg: the soft context pointer
*
- * Unsused
- *
* LOCKING:
* Internally locks the context
*
*/
-static void
+static int
ti_gpio_intr(void *arg)
{
- struct ti_gpio_softc *sc = arg;
+ int bank_last, irq;
+ struct intr_event *event;
+ struct ti_gpio_softc *sc;
+ uint32_t reg;
- TI_GPIO_LOCK(sc);
- /* TODO: something useful */
- TI_GPIO_UNLOCK(sc);
+ sc = (struct ti_gpio_softc *)arg;
+ bank_last = -1;
+ reg = 0; /* squelch bogus gcc warning */
+ for (irq = 0; irq < sc->sc_maxpin; irq++) {
+
+ /* Read interrupt status only once for each bank. */
+ if (TI_GPIO_BANK(irq) != bank_last) {
+ reg = ti_gpio_intr_status(sc, TI_GPIO_BANK(irq));
+ bank_last = TI_GPIO_BANK(irq);
+ }
+ if ((reg & TI_GPIO_MASK(irq)) == 0)
+ continue;
+ event = sc->sc_events[irq];
+ if (event != NULL && !TAILQ_EMPTY(&event->ie_handlers))
+ intr_event_handle(event, NULL);
+ else
+ device_printf(sc->sc_dev, "Stray IRQ %d\n", irq);
+ /* Ack the IRQ Status bit. */
+ ti_gpio_intr_ack(sc, TI_GPIO_BANK(irq), TI_GPIO_MASK(irq));
+ }
+
+ return (FILTER_HANDLED);
}
static int
@@ -643,13 +652,13 @@ ti_gpio_attach_intr(device_t dev)
break;
/*
- * Register our interrupt handler for each of the IRQ resources.
+ * Register our interrupt filter for each of the IRQ resources.
*/
if (bus_setup_intr(dev, sc->sc_irq_res[i],
- INTR_TYPE_MISC | INTR_MPSAFE, NULL, ti_gpio_intr, sc,
+ INTR_TYPE_MISC | INTR_MPSAFE, ti_gpio_intr, NULL, sc,
&sc->sc_irq_hdl[i]) != 0) {
device_printf(dev,
- "WARNING: unable to register interrupt handler\n");
+ "WARNING: unable to register interrupt filter\n");
return (-1);
}
}
@@ -663,7 +672,7 @@ ti_gpio_detach_intr(device_t dev)
int i;
struct ti_gpio_softc *sc;
- /* Teardown our interrupt handlers. */
+ /* Teardown our interrupt filters. */
sc = device_get_softc(dev);
for (i = 0; i < ti_max_gpio_intrs(); i++) {
if (sc->sc_irq_res[i] == NULL)
@@ -683,7 +692,7 @@ ti_gpio_bank_init(device_t dev, int bank)
{
int pin;
struct ti_gpio_softc *sc;
- uint32_t flags, reg_oe;
+ uint32_t flags, reg_oe, rev;
sc = device_get_softc(dev);
@@ -695,13 +704,12 @@ ti_gpio_bank_init(device_t dev, int bank)
* actual revision numbers, so instead the values have been
* determined by experimentation.
*/
- sc->sc_revision[bank] = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
+ rev = ti_gpio_read_4(sc, bank, TI_GPIO_REVISION);
/* Check the revision. */
- if (sc->sc_revision[bank] != ti_gpio_rev()) {
+ if (rev != ti_gpio_rev()) {
device_printf(dev, "Warning: could not determine the revision "
- "of %u GPIO module (revision:0x%08x)\n",
- bank, sc->sc_revision[bank]);
+ "of GPIO module %d (revision:0x%08x)\n", bank, rev);
return (EINVAL);
}
@@ -740,10 +748,13 @@ ti_gpio_attach(device_t dev)
unsigned int i;
int err;
- sc = device_get_softc(dev);
- sc->sc_dev = dev;
+ if (ti_gpio_sc != NULL)
+ return (ENXIO);
+ ti_gpio_sc = sc = device_get_softc(dev);
+ sc->sc_dev = dev;
TI_GPIO_LOCK_INIT(sc);
+ ti_gpio_pin_max(dev, &sc->sc_maxpin);
/* There are up to 6 different GPIO register sets located in different
* memory areas on the chip. The memory range should have been set for
@@ -769,6 +780,24 @@ ti_gpio_attach(device_t dev)
return (ENXIO);
}
+ /*
+ * Initialize the interrupt settings. The default is active-low
+ * interrupts.
+ */
+ sc->sc_irq_trigger = malloc(
+ sizeof(*sc->sc_irq_trigger) * sc->sc_maxpin,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ sc->sc_irq_polarity = malloc(
+ sizeof(*sc->sc_irq_polarity) * sc->sc_maxpin,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ for (i = 0; i < sc->sc_maxpin; i++) {
+ sc->sc_irq_trigger[i] = INTR_TRIGGER_LEVEL;
+ sc->sc_irq_polarity[i] = INTR_POLARITY_LOW;
+ }
+
+ sc->sc_events = malloc(sizeof(struct intr_event *) * sc->sc_maxpin,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
/* We need to go through each block and ensure the clocks are running and
* the module is enabled. It might be better to do this only when the
* pins are configured which would result in less power used if the GPIO
@@ -825,6 +854,10 @@ ti_gpio_detach(device_t dev)
bus_generic_detach(dev);
+ free(sc->sc_events, M_DEVBUF);
+ free(sc->sc_irq_polarity, M_DEVBUF);
+ free(sc->sc_irq_trigger, M_DEVBUF);
+
/* Release the memory and IRQ resources. */
ti_gpio_detach_intr(dev);
bus_release_resources(dev, ti_gpio_irq_spec, sc->sc_irq_res);
@@ -835,6 +868,193 @@ ti_gpio_detach(device_t dev)
return (0);
}
+static uint32_t
+ti_gpio_intr_reg(struct ti_gpio_softc *sc, int irq)
+{
+
+ if (ti_gpio_valid_pin(sc, irq) != 0)
+ return (0);
+
+ if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_LEVEL) {
+ if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
+ return (TI_GPIO_LEVELDETECT0);
+ else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
+ return (TI_GPIO_LEVELDETECT1);
+ } else if (sc->sc_irq_trigger[irq] == INTR_TRIGGER_EDGE) {
+ if (sc->sc_irq_polarity[irq] == INTR_POLARITY_LOW)
+ return (TI_GPIO_FALLINGDETECT);
+ else if (sc->sc_irq_polarity[irq] == INTR_POLARITY_HIGH)
+ return (TI_GPIO_RISINGDETECT);
+ }
+
+ return (0);
+}
+
+static void
+ti_gpio_mask_irq(void *source)
+{
+ int irq;
+ uint32_t reg, val;
+
+ irq = (int)source;
+ if (ti_gpio_valid_pin(ti_gpio_sc, irq) != 0)
+ return;
+
+ TI_GPIO_LOCK(ti_gpio_sc);
+ ti_gpio_intr_clr(ti_gpio_sc, TI_GPIO_BANK(irq), TI_GPIO_MASK(irq));
+ reg = ti_gpio_intr_reg(ti_gpio_sc, irq);
+ if (reg != 0) {
+ val = ti_gpio_read_4(ti_gpio_sc, TI_GPIO_BANK(irq), reg);
+ val &= ~TI_GPIO_MASK(irq);
+ ti_gpio_write_4(ti_gpio_sc, TI_GPIO_BANK(irq), reg, val);
+ }
+ TI_GPIO_UNLOCK(ti_gpio_sc);
+}
+
+static void
+ti_gpio_unmask_irq(void *source)
+{
+ int irq;
+ uint32_t reg, val;
+
+ irq = (int)source;
+ if (ti_gpio_valid_pin(ti_gpio_sc, irq) != 0)
+ return;
+
+ TI_GPIO_LOCK(ti_gpio_sc);
+ reg = ti_gpio_intr_reg(ti_gpio_sc, irq);
+ if (reg != 0) {
+ val = ti_gpio_read_4(ti_gpio_sc, TI_GPIO_BANK(irq), reg);
+ val |= TI_GPIO_MASK(irq);
+ ti_gpio_write_4(ti_gpio_sc, TI_GPIO_BANK(irq), reg, val);
+ ti_gpio_intr_set(ti_gpio_sc, TI_GPIO_BANK(irq),
+ TI_GPIO_MASK(irq));
+ }
+ TI_GPIO_UNLOCK(ti_gpio_sc);
+}
+
+static int
+ti_gpio_activate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *res)
+{
+ int pin;
+
+ if (type != SYS_RES_IRQ)
+ return (ENXIO);
+
+ /* Unmask the interrupt. */
+ pin = rman_get_start(res);
+ ti_gpio_unmask_irq((void *)(uintptr_t)pin);
+
+ return (0);
+}
+
+static int
+ti_gpio_deactivate_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *res)
+{
+ int pin;
+
+ if (type != SYS_RES_IRQ)
+ return (ENXIO);
+
+ /* Mask the interrupt. */
+ pin = rman_get_start(res);
+ ti_gpio_mask_irq((void *)(uintptr_t)pin);
+
+ return (0);
+}
+
+static int
+ti_gpio_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+ struct ti_gpio_softc *sc;
+ uint32_t oldreg, reg, val;
+
+ sc = device_get_softc(dev);
+ if (ti_gpio_valid_pin(sc, irq) != 0)
+ return (EINVAL);
+
+ /* There is no standard trigger or polarity. */
+ if (trig == INTR_TRIGGER_CONFORM || pol == INTR_POLARITY_CONFORM)
+ return (EINVAL);
+
+ TI_GPIO_LOCK(sc);
+ /*
+ * TRM recommends add the new event before remove the old one to
+ * avoid losing interrupts.
+ */
+ oldreg = ti_gpio_intr_reg(sc, irq);
+ sc->sc_irq_trigger[irq] = trig;
+ sc->sc_irq_polarity[irq] = pol;
+ reg = ti_gpio_intr_reg(sc, irq);
+ if (reg != 0) {
+ /* Apply the new settings. */
+ val = ti_gpio_read_4(sc, TI_GPIO_BANK(irq), reg);
+ val |= TI_GPIO_MASK(irq);
+ ti_gpio_write_4(sc, TI_GPIO_BANK(irq), reg, val);
+ }
+ if (oldreg != 0) {
+ /* Remove the old settings. */
+ val = ti_gpio_read_4(sc, TI_GPIO_BANK(irq), oldreg);
+ val &= ~TI_GPIO_MASK(irq);
+ ti_gpio_write_4(sc, TI_GPIO_BANK(irq), oldreg, val);
+ }
+ TI_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+ti_gpio_setup_intr(device_t dev, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *handler,
+ void *arg, void **cookiep)
+{
+ struct ti_gpio_softc *sc;
+ struct intr_event *event;
+ int pin, error;
+
+ sc = device_get_softc(dev);
+ pin = rman_get_start(ires);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
+ panic("%s: bad pin %d", __func__, pin);
+
+ event = sc->sc_events[pin];
+ if (event == NULL) {
+ error = intr_event_create(&event, (void *)(uintptr_t)pin, 0,
+ pin, ti_gpio_mask_irq, ti_gpio_unmask_irq, NULL, NULL,
+ "gpio%d pin%d:", device_get_unit(dev), pin);
+ if (error != 0)
+ return (error);
+ sc->sc_events[pin] = event;
+ }
+ intr_event_add_handler(event, device_get_nameunit(child), filt,
+ handler, arg, intr_priority(flags), flags, cookiep);
+
+ return (0);
+}
+
+static int
+ti_gpio_teardown_intr(device_t dev, device_t child, struct resource *ires,
+ void *cookie)
+{
+ struct ti_gpio_softc *sc;
+ int pin, err;
+
+ sc = device_get_softc(dev);
+ pin = rman_get_start(ires);
+ if (ti_gpio_valid_pin(sc, pin) != 0)
+ panic("%s: bad pin %d", __func__, pin);
+ if (sc->sc_events[pin] == NULL)
+ panic("Trying to teardown unoccupied IRQ");
+ err = intr_event_remove_handler(cookie);
+ if (!err)
+ sc->sc_events[pin] = NULL;
+
+ return (err);
+}
+
static phandle_t
ti_gpio_get_node(device_t bus, device_t dev)
{
@@ -857,6 +1077,13 @@ static device_method_t ti_gpio_methods[] = {
DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
+ /* Bus interface */
+ DEVMETHOD(bus_activate_resource, ti_gpio_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, ti_gpio_deactivate_resource),
+ DEVMETHOD(bus_config_intr, ti_gpio_config_intr),
+ DEVMETHOD(bus_setup_intr, ti_gpio_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ti_gpio_teardown_intr),
+
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h
index 0e1199f..763fc8a 100644
--- a/sys/arm/ti/ti_gpio.h
+++ b/sys/arm/ti/ti_gpio.h
@@ -47,6 +47,13 @@
struct ti_gpio_softc {
device_t sc_dev;
+ /* Interrupt trigger type and level. */
+ enum intr_trigger *sc_irq_trigger;
+ enum intr_polarity *sc_irq_polarity;
+
+ int sc_maxpin;
+ struct mtx sc_mtx;
+
/*
* The memory resource(s) for the PRCM register set, when the device is
* created the caller can assign up to 6 memory regions depending on
@@ -55,15 +62,11 @@ struct ti_gpio_softc {
struct resource *sc_mem_res[MAX_GPIO_BANKS];
struct resource *sc_irq_res[MAX_GPIO_INTRS];
+ /* Interrupt events. */
+ struct intr_event **sc_events;
+
/* The handle for the register IRQ handlers. */
void *sc_irq_hdl[MAX_GPIO_INTRS];
-
- /*
- * The following describes the H/W revision of each of the GPIO banks.
- */
- uint32_t sc_revision[MAX_GPIO_BANKS];
-
- struct mtx sc_mtx;
};
#endif /* TI_GPIO_H */
diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c
index 8f9af0c..d304827 100644
--- a/sys/arm/ti/ti_i2c.c
+++ b/sys/arm/ti/ti_i2c.c
@@ -119,7 +119,7 @@ struct ti_i2c_clock_config
static struct ti_i2c_clock_config ti_omap4_i2c_clock_configs[] = {
{ 100000, 23, 13, 15, 0, 0},
{ 400000, 9, 5, 7, 0, 0},
- { 1000000, 5, 1, 3, 0, 0},
+ { 1000000, 3, 5, 7, 0, 0},
/* { 3200000, 1, 113, 115, 7, 10}, - HS mode */
{ 0 /* Table terminator */ }
};
diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c
index 024c830..380a40e 100644
--- a/sys/arm/ti/ti_sdhci.c
+++ b/sys/arm/ti/ti_sdhci.c
@@ -112,6 +112,7 @@ static struct ofw_compat_data compat_data[] = {
#define MMCHS_CON 0x02C
#define MMCHS_CON_DW8 (1 << 5)
#define MMCHS_CON_DVAL_8_4MS (3 << 9)
+#define MMCHS_CON_OD (1 << 0)
#define MMCHS_SYSCTL 0x12C
#define MMCHS_SYSCTL_CLKD_MASK 0x3FF
#define MMCHS_SYSCTL_CLKD_SHIFT 6
@@ -327,7 +328,7 @@ ti_sdhci_update_ios(device_t brdev, device_t reqdev)
struct ti_sdhci_softc *sc = device_get_softc(brdev);
struct sdhci_slot *slot;
struct mmc_ios *ios;
- uint32_t val32;
+ uint32_t val32, newval32;
slot = device_get_ivars(reqdev);
ios = &slot->host.ios;
@@ -339,10 +340,20 @@ ti_sdhci_update_ios(device_t brdev, device_t reqdev)
* requested, then let the standard driver handle everything else.
*/
val32 = ti_mmchs_read_4(sc, MMCHS_CON);
+ newval32 = val32;
+
if (ios->bus_width == bus_width_8)
- ti_mmchs_write_4(sc, MMCHS_CON, val32 | MMCHS_CON_DW8);
+ newval32 |= MMCHS_CON_DW8;
else
- ti_mmchs_write_4(sc, MMCHS_CON, val32 & ~MMCHS_CON_DW8);
+ newval32 &= ~MMCHS_CON_DW8;
+
+ if (ios->bus_mode == opendrain)
+ newval32 |= MMCHS_CON_OD;
+ else /* if (ios->bus_mode == pushpull) */
+ newval32 &= ~MMCHS_CON_OD;
+
+ if (newval32 != val32)
+ ti_mmchs_write_4(sc, MMCHS_CON, newval32);
return (sdhci_generic_update_ios(brdev, reqdev));
}
@@ -392,20 +403,42 @@ ti_sdhci_hw_init(device_t dev)
/* Issue a softreset to the controller */
ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
timeout = 1000;
- while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & MMCHS_SYSSTATUS_RESETDONE)) {
+ while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) &
+ MMCHS_SYSSTATUS_RESETDONE)) {
if (--timeout == 0) {
- device_printf(dev, "Error: Controller reset operation timed out\n");
+ device_printf(dev,
+ "Error: Controller reset operation timed out\n");
break;
}
DELAY(100);
}
- /* Reset both the command and data state machines */
+ /*
+ * Reset the command and data state machines and also other aspects of
+ * the controller such as bus clock and power.
+ *
+ * If we read the software reset register too fast after writing it we
+ * can get back a zero that means the reset hasn't started yet rather
+ * than that the reset is complete. Per TI recommendations, work around
+ * it by reading until we see the reset bit asserted, then read until
+ * it's clear. We also set the SDHCI_QUIRK_WAITFOR_RESET_ASSERTED quirk
+ * so that the main sdhci driver uses this same logic in its resets.
+ */
ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL);
- timeout = 1000;
- while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL)) {
+ timeout = 10000;
+ while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
+ SDHCI_RESET_ALL) != SDHCI_RESET_ALL) {
if (--timeout == 0) {
- device_printf(dev, "Error: Software reset operation timed out\n");
+ break;
+ }
+ DELAY(1);
+ }
+ timeout = 10000;
+ while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
+ SDHCI_RESET_ALL)) {
+ if (--timeout == 0) {
+ device_printf(dev,
+ "Error: Software reset operation timed out\n");
break;
}
DELAY(100);
@@ -568,6 +601,12 @@ ti_sdhci_attach(device_t dev)
sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
/*
+ * Reset bits are broken, have to wait to see the bits asserted
+ * before waiting to see them de-asserted.
+ */
+ sc->slot.quirks |= SDHCI_QUIRK_WAITFOR_RESET_ASSERTED;
+
+ /*
* DMA is not really broken, I just haven't implemented it yet.
*/
sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
diff --git a/sys/arm/ti/ti_wdt.c b/sys/arm/ti/ti_wdt.c
index 7f50a61..7e8e5ae 100644
--- a/sys/arm/ti/ti_wdt.c
+++ b/sys/arm/ti/ti_wdt.c
@@ -95,7 +95,7 @@ static devclass_t ti_wdt_devclass;
DRIVER_MODULE(ti_wdt, simplebus, ti_wdt_driver, ti_wdt_devclass, 0, 0);
-static volatile __inline uint32_t
+static __inline uint32_t
ti_wdt_reg_read(struct ti_wdt_softc *sc, uint32_t reg)
{
diff --git a/sys/arm/xilinx/std.zynq7 b/sys/arm/xilinx/std.zynq7
index 1cee32d..34e6739 100644
--- a/sys/arm/xilinx/std.zynq7
+++ b/sys/arm/xilinx/std.zynq7
@@ -5,6 +5,7 @@
cpu CPU_CORTEXA
machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
files "../xilinx/files.zynq7"
diff --git a/sys/boot/amd64/boot1.efi/Makefile b/sys/boot/amd64/boot1.efi/Makefile
index 3e3bc9f..dd8eaf9 100644
--- a/sys/boot/amd64/boot1.efi/Makefile
+++ b/sys/boot/amd64/boot1.efi/Makefile
@@ -51,7 +51,7 @@ boot1.efi: loader.sym
${OBJCOPY} -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
- --target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
+ --output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
CFLAGS+= -I${.CURDIR}/../../common
diff --git a/sys/boot/amd64/boot1.efi/generate-fat.sh b/sys/boot/amd64/boot1.efi/generate-fat.sh
index eafd3e0..e8f9cde 100755
--- a/sys/boot/amd64/boot1.efi/generate-fat.sh
+++ b/sys/boot/amd64/boot1.efi/generate-fat.sh
@@ -34,10 +34,10 @@ umount stub
mdconfig -d -u $DEVICE
rmdir stub
-# Locate the offsets of the two fake files
+# Locate the offset of the fake file
BOOT1_OFFSET=$(hd $OUTPUT_FILE | grep 'Boot1 START' | cut -f 1 -d ' ')
-# Convert to numbers of blocks
+# Convert to number of blocks
BOOT1_OFFSET=$(echo 0x$BOOT1_OFFSET | awk '{printf("%x\n",$1/512);}')
echo '# This file autogenerated by generate-fat.sh - DO NOT EDIT' > Makefile.fat
diff --git a/sys/boot/amd64/efi/Makefile b/sys/boot/amd64/efi/Makefile
index a9a2132..66b8cf8 100644
--- a/sys/boot/amd64/efi/Makefile
+++ b/sys/boot/amd64/efi/Makefile
@@ -81,7 +81,7 @@ loader.efi: loader.sym
${OBJCOPY} -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
-j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
- --target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
+ --output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
LIBEFI= ${.OBJDIR}/../../efi/libefi/libefi.a
CFLAGS+= -I${.CURDIR}/../../common
diff --git a/sys/boot/arm/uboot/Makefile b/sys/boot/arm/uboot/Makefile
index 743f189..c69d8aa 100644
--- a/sys/boot/arm/uboot/Makefile
+++ b/sys/boot/arm/uboot/Makefile
@@ -76,7 +76,7 @@ LIBUBOOT_FDT= ${.OBJDIR}/../../uboot/fdt/libuboot_fdt.a
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
.endif
-.if !defined(NO_FORTH)
+.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/arm
diff --git a/sys/boot/common/console.c b/sys/boot/common/console.c
index 6c1fdab..6656eab 100644
--- a/sys/boot/common/console.c
+++ b/sys/boot/common/console.c
@@ -39,6 +39,7 @@ static int cons_set(struct env_var *ev, int flags, const void *value);
static int cons_find(const char *name);
static int cons_check(const char *string);
static void cons_change(const char *string);
+static int twiddle_set(struct env_var *ev, int flags, const void *value);
/*
* Detect possible console(s) to use. If preferred console(s) have been
@@ -52,6 +53,9 @@ cons_probe(void)
int active;
char *prefconsole;
+ /* We want a callback to install the new value when this var changes. */
+ env_setenv("twiddle_divisor", EV_VOLATILE, "1", twiddle_set, env_nounset);
+
/* Do all console probes */
for (cons = 0; consoles[cons] != NULL; cons++) {
consoles[cons]->c_flags = 0;
@@ -232,3 +236,28 @@ cons_change(const char *string)
free(dup);
}
+
+/*
+ * Change the twiddle divisor.
+ *
+ * The user can set the twiddle_divisor variable to directly control how fast
+ * the progress twiddle spins, useful for folks with slow serial consoles. The
+ * code to monitor changes to the variable and propagate them to the twiddle
+ * routines has to live somewhere. Twiddling is console-related so it's here.
+ */
+static int
+twiddle_set(struct env_var *ev, int flags, const void *value)
+{
+ u_long tdiv;
+ char * eptr;
+
+ tdiv = strtoul(value, &eptr, 0);
+ if (*(const char *)value == 0 || *eptr != 0) {
+ printf("invalid twiddle_divisor '%s'\n", (const char *)value);
+ return (CMD_ERROR);
+ }
+ twiddle_divisor((u_int)tdiv);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+
+ return(CMD_OK);
+}
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index fe247ac..cac5674 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 1, 2013
+.Dd December 22, 2014
.Dt LOADER 8
.Os
.Sh NAME
@@ -670,6 +670,12 @@ Overrides the compile-time set value of
.Dv TCBHASHSIZE
or the preset default of 512.
Must be a power of 2.
+.It Va twiddle_divisor
+Throttles the output of the `twiddle' I/O progress indicator displayed
+while loading the kernel and modules.
+This is useful on slow serial consoles where the time spent waiting for
+these characters to be written can add up to many seconds.
+The default is 1 (full speed); a value of 2 spins half as fast, and so on.
.It Va vm.kmem_size
Sets the size of kernel memory (bytes).
This overrides the value determined when the kernel was compiled.
diff --git a/sys/boot/fdt/dts/arm/am335x.dtsi b/sys/boot/fdt/dts/arm/am335x.dtsi
index 9378f34..feb32f2 100644
--- a/sys/boot/fdt/dts/arm/am335x.dtsi
+++ b/sys/boot/fdt/dts/arm/am335x.dtsi
@@ -99,6 +99,8 @@
0x481AE000 0x1000 >;
interrupts = < 96 97 98 99 32 33 62 63 >;
interrupt-parent = <&AINTC>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
};
uart0: serial@44E09000 {
diff --git a/sys/boot/fdt/dts/arm/rpi.dts b/sys/boot/fdt/dts/arm/rpi.dts
index 58ceaa4..08d9d24 100644
--- a/sys/boot/fdt/dts/arm/rpi.dts
+++ b/sys/boot/fdt/dts/arm/rpi.dts
@@ -35,6 +35,17 @@
memreserve = <0x08000000 0x08000000>; /* Set by VideoCore */
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ compatible = "arm,1176jzf-s";
+ device_type = "cpu";
+ reg = <0>; /* CPU ID=0 */
+ clock-frequency = <700000000>; /* 700MHz */
+ };
+ };
+
memory {
device_type = "memory";
reg = <0 0x8000000>; /* 128MB, Set by VideoCore */
diff --git a/sys/boot/forth/brand.4th.8 b/sys/boot/forth/brand.4th.8
index 64e6854..dfd188d 100644
--- a/sys/boot/forth/brand.4th.8
+++ b/sys/boot/forth/brand.4th.8
@@ -111,7 +111,7 @@ loader_brand="fbsd"
.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
-.Xr loader 8 ,
+.Xr loader 8
.Sh HISTORY
The
.Nm
diff --git a/sys/boot/forth/delay.4th.8 b/sys/boot/forth/delay.4th.8
index dd1680e..af31fd0 100644
--- a/sys/boot/forth/delay.4th.8
+++ b/sys/boot/forth/delay.4th.8
@@ -110,8 +110,8 @@ delay_execute
.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
-.Xr loader 8 ,
.Xr beastie.4th 8 ,
+.Xr loader 8 ,
.Xr loader.4th 8
.Sh HISTORY
The
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index bd7d296..fd0b0de 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -75,6 +75,7 @@ module_path="/boot/modules" # Set the module search path
# the block size is set to 512. If the value
# is out of range ( < 8 || > 9008 ) an error is
# returned.
+#twiddle_divisor="1" # >1 means slow down the progress indicator.
##############################################################
diff --git a/sys/boot/forth/menu.4th.8 b/sys/boot/forth/menu.4th.8
index ab67d73..3673eec 100644
--- a/sys/boot/forth/menu.4th.8
+++ b/sys/boot/forth/menu.4th.8
@@ -336,9 +336,9 @@ menu-display
.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
+.Xr beastie.4th 8 ,
.Xr loader 8 ,
-.Xr loader.4th 8 ,
-.Xr beastie.4th 8
+.Xr loader.4th 8
.Sh HISTORY
The
.Nm
diff --git a/sys/boot/forth/menusets.4th.8 b/sys/boot/forth/menusets.4th.8
index e05e4a7..f785ae1 100644
--- a/sys/boot/forth/menusets.4th.8
+++ b/sys/boot/forth/menusets.4th.8
@@ -355,10 +355,10 @@ set submenu_command[1]="1 goto_menu"
.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
+.Xr beastie.4th 8 ,
.Xr loader 8 ,
.Xr loader.4th 8 ,
-.Xr menu.4th 8 ,
-.Xr beastie.4th 8
+.Xr menu.4th 8
.Sh HISTORY
The
.Nm
diff --git a/sys/boot/forth/version.4th.8 b/sys/boot/forth/version.4th.8
index fe8b618..256df1e 100644
--- a/sys/boot/forth/version.4th.8
+++ b/sys/boot/forth/version.4th.8
@@ -113,8 +113,8 @@ loader_version="loader 1.1"
.Ed
.Sh SEE ALSO
.Xr loader.conf 5 ,
-.Xr loader 8 ,
-.Xr color.4th 8
+.Xr color.4th 8 ,
+.Xr loader 8
.Sh HISTORY
The
.Nm
diff --git a/sys/boot/i386/libi386/spinconsole.c b/sys/boot/i386/libi386/spinconsole.c
index 752c29f..161d810 100644
--- a/sys/boot/i386/libi386/spinconsole.c
+++ b/sys/boot/i386/libi386/spinconsole.c
@@ -86,9 +86,11 @@ spinc_putchar(int c)
if (now < (lasttime + 1))
return;
lasttime = now;
+#ifdef TERM_EMU
get_pos(&curx, &cury);
if (curx > 0)
curs_move(&curx, &cury, curx - 1, cury);
+#endif
vidc_biosputchar((char)tw_chars);
tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);
}
diff --git a/sys/boot/powerpc/uboot/Makefile b/sys/boot/powerpc/uboot/Makefile
index a5a06a9..681249a 100644
--- a/sys/boot/powerpc/uboot/Makefile
+++ b/sys/boot/powerpc/uboot/Makefile
@@ -66,7 +66,7 @@ LIBUBOOT_FDT= ${.OBJDIR}/../../uboot/fdt/libuboot_fdt.a
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
.endif
-.if !defined(NO_FORTH)
+.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/powerpc
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index ae77766..f58d0c4 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -212,10 +212,11 @@ get_load_device(int *type, int *unit, int *slice, int *partition)
p = get_device_type(devstr, type);
- /*
- * Empty device string, or unknown device name, or a bare, known
- * device name.
- */
+ /* Ignore optional spaces after the device name. */
+ while (*p == ' ')
+ p++;
+
+ /* Unknown device name, or a known name without unit number. */
if ((*type == -1) || (*p == '\0')) {
return;
}
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 8fccd02..e90a029 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -111,7 +111,7 @@ struct ctl_softc *control_softc = NULL;
* Note that these are default values only. The actual values will be
* filled in when the user does a mode sense.
*/
-static struct copan_debugconf_subpage debugconf_page_default = {
+const static struct copan_debugconf_subpage debugconf_page_default = {
DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */
DBGCNF_SUBPAGE_CODE, /* subpage */
{(sizeof(struct copan_debugconf_subpage) - 4) >> 8,
@@ -121,7 +121,7 @@ static struct copan_debugconf_subpage debugconf_page_default = {
CTL_TIME_IO_DEFAULT_SECS>>0}, /* ctl_time_io_secs */
};
-static struct copan_debugconf_subpage debugconf_page_changeable = {
+const static struct copan_debugconf_subpage debugconf_page_changeable = {
DBGCNF_PAGE_CODE | SMPH_SPF, /* page_code */
DBGCNF_SUBPAGE_CODE, /* subpage */
{(sizeof(struct copan_debugconf_subpage) - 4) >> 8,
@@ -130,7 +130,7 @@ static struct copan_debugconf_subpage debugconf_page_changeable = {
{0xff,0xff}, /* ctl_time_io_secs */
};
-static struct scsi_da_rw_recovery_page rw_er_page_default = {
+const static struct scsi_da_rw_recovery_page rw_er_page_default = {
/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
/*byte3*/SMS_RWER_AWRE|SMS_RWER_ARRE,
@@ -144,7 +144,7 @@ static struct scsi_da_rw_recovery_page rw_er_page_default = {
/*recovery_time_limit*/{0, 0},
};
-static struct scsi_da_rw_recovery_page rw_er_page_changeable = {
+const static struct scsi_da_rw_recovery_page rw_er_page_changeable = {
/*page_code*/SMS_RW_ERROR_RECOVERY_PAGE,
/*page_length*/sizeof(struct scsi_da_rw_recovery_page) - 2,
/*byte3*/0,
@@ -158,7 +158,7 @@ static struct scsi_da_rw_recovery_page rw_er_page_changeable = {
/*recovery_time_limit*/{0, 0},
};
-static struct scsi_format_page format_page_default = {
+const static struct scsi_format_page format_page_default = {
/*page_code*/SMS_FORMAT_DEVICE_PAGE,
/*page_length*/sizeof(struct scsi_format_page) - 2,
/*tracks_per_zone*/ {0, 0},
@@ -175,7 +175,7 @@ static struct scsi_format_page format_page_default = {
/*reserved*/ {0, 0, 0}
};
-static struct scsi_format_page format_page_changeable = {
+const static struct scsi_format_page format_page_changeable = {
/*page_code*/SMS_FORMAT_DEVICE_PAGE,
/*page_length*/sizeof(struct scsi_format_page) - 2,
/*tracks_per_zone*/ {0, 0},
@@ -191,7 +191,7 @@ static struct scsi_format_page format_page_changeable = {
/*reserved*/ {0, 0, 0}
};
-static struct scsi_rigid_disk_page rigid_disk_page_default = {
+const static struct scsi_rigid_disk_page rigid_disk_page_default = {
/*page_code*/SMS_RIGID_DISK_PAGE,
/*page_length*/sizeof(struct scsi_rigid_disk_page) - 2,
/*cylinders*/ {0, 0, 0},
@@ -208,7 +208,7 @@ static struct scsi_rigid_disk_page rigid_disk_page_default = {
/*reserved2*/ {0, 0}
};
-static struct scsi_rigid_disk_page rigid_disk_page_changeable = {
+const static struct scsi_rigid_disk_page rigid_disk_page_changeable = {
/*page_code*/SMS_RIGID_DISK_PAGE,
/*page_length*/sizeof(struct scsi_rigid_disk_page) - 2,
/*cylinders*/ {0, 0, 0},
@@ -224,7 +224,7 @@ static struct scsi_rigid_disk_page rigid_disk_page_changeable = {
/*reserved2*/ {0, 0}
};
-static struct scsi_caching_page caching_page_default = {
+const static struct scsi_caching_page caching_page_default = {
/*page_code*/SMS_CACHING_PAGE,
/*page_length*/sizeof(struct scsi_caching_page) - 2,
/*flags1*/ SCP_DISC | SCP_WCE,
@@ -240,7 +240,7 @@ static struct scsi_caching_page caching_page_default = {
/*non_cache_seg_size*/ {0, 0, 0}
};
-static struct scsi_caching_page caching_page_changeable = {
+const static struct scsi_caching_page caching_page_changeable = {
/*page_code*/SMS_CACHING_PAGE,
/*page_length*/sizeof(struct scsi_caching_page) - 2,
/*flags1*/ SCP_WCE | SCP_RCD,
@@ -256,7 +256,7 @@ static struct scsi_caching_page caching_page_changeable = {
/*non_cache_seg_size*/ {0, 0, 0}
};
-static struct scsi_control_page control_page_default = {
+const static struct scsi_control_page control_page_default = {
/*page_code*/SMS_CONTROL_MODE_PAGE,
/*page_length*/sizeof(struct scsi_control_page) - 2,
/*rlec*/0,
@@ -268,7 +268,7 @@ static struct scsi_control_page control_page_default = {
/*extended_selftest_completion_time*/{0, 0}
};
-static struct scsi_control_page control_page_changeable = {
+const static struct scsi_control_page control_page_changeable = {
/*page_code*/SMS_CONTROL_MODE_PAGE,
/*page_length*/sizeof(struct scsi_control_page) - 2,
/*rlec*/SCP_DSENSE,
@@ -280,7 +280,7 @@ static struct scsi_control_page control_page_changeable = {
/*extended_selftest_completion_time*/{0, 0}
};
-static struct scsi_info_exceptions_page ie_page_default = {
+const static struct scsi_info_exceptions_page ie_page_default = {
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
/*info_flags*/SIEP_FLAGS_DEXCPT,
@@ -289,7 +289,7 @@ static struct scsi_info_exceptions_page ie_page_default = {
/*report_count*/{0, 0, 0, 0}
};
-static struct scsi_info_exceptions_page ie_page_changeable = {
+const static struct scsi_info_exceptions_page ie_page_changeable = {
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE,
/*page_length*/sizeof(struct scsi_info_exceptions_page) - 2,
/*info_flags*/0,
@@ -300,7 +300,7 @@ static struct scsi_info_exceptions_page ie_page_changeable = {
#define CTL_LBPM_LEN (sizeof(struct ctl_logical_block_provisioning_page) - 4)
-static struct ctl_logical_block_provisioning_page lbp_page_default = {{
+const static struct ctl_logical_block_provisioning_page lbp_page_default = {{
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF,
/*subpage_code*/0x02,
/*page_length*/{CTL_LBPM_LEN >> 8, CTL_LBPM_LEN},
@@ -326,7 +326,7 @@ static struct ctl_logical_block_provisioning_page lbp_page_default = {{
}
};
-static struct ctl_logical_block_provisioning_page lbp_page_changeable = {{
+const static struct ctl_logical_block_provisioning_page lbp_page_changeable = {{
/*page_code*/SMS_INFO_EXCEPTIONS_PAGE | SMPH_SPF,
/*subpage_code*/0x02,
/*page_length*/{CTL_LBPM_LEN >> 8, CTL_LBPM_LEN},
@@ -398,8 +398,8 @@ static int ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num,
struct ctl_ooa_entry *kern_entries);
static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td);
-static uint32_t ctl_map_lun(int port_num, uint32_t lun);
-static uint32_t ctl_map_lun_back(int port_num, uint32_t lun);
+static uint32_t ctl_map_lun(struct ctl_softc *softc, int port_num, uint32_t lun);
+static uint32_t ctl_map_lun_back(struct ctl_softc *softc, int port_num, uint32_t lun);
static int ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
struct ctl_be_lun *be_lun, struct ctl_id target_id);
static int ctl_free_lun(struct ctl_lun *lun);
@@ -441,8 +441,7 @@ static ctl_action ctl_check_for_blockage(struct ctl_lun *lun,
static ctl_action ctl_check_ooa(struct ctl_lun *lun, union ctl_io *pending_io,
union ctl_io *starting_io);
static int ctl_check_blocked(struct ctl_lun *lun);
-static int ctl_scsiio_lun_check(struct ctl_softc *ctl_softc,
- struct ctl_lun *lun,
+static int ctl_scsiio_lun_check(struct ctl_lun *lun,
const struct ctl_cmd_entry *entry,
struct ctl_scsiio *ctsio);
//static int ctl_check_rtr(union ctl_io *pending_io, struct ctl_softc *softc);
@@ -609,12 +608,12 @@ ctl_isc_handler_finish_ser_only(struct ctl_softc *ctl_softc,
static void
ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
union ctl_io *io;
struct ctl_prio *presio;
ctl_ha_status isc_status;
- ctl_softc = control_softc;
+ softc = control_softc;
io = NULL;
@@ -640,7 +639,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
#if 0
printf("Serialize\n");
#endif
- io = ctl_alloc_io_nowait(ctl_softc->othersc_pool);
+ io = ctl_alloc_io_nowait(softc->othersc_pool);
if (io == NULL) {
printf("ctl_isc_event_handler: can't allocate "
"ctl_io!\n");
@@ -672,7 +671,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
*
* XXX KDM add another flag that is more specific.
*/
- if (ctl_softc->ha_mode == CTL_HA_MODE_SER_ONLY)
+ if (softc->ha_mode == CTL_HA_MODE_SER_ONLY)
io->io_hdr.flags |= CTL_FLAG_INT_COPY;
io->io_hdr.nexus = msg_info.hdr.nexus;
#if 0
@@ -686,7 +685,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
io->scsiio.tag_type = msg_info.scsi.tag_type;
memcpy(io->scsiio.cdb, msg_info.scsi.cdb,
CTL_MAX_CDBLEN);
- if (ctl_softc->ha_mode == CTL_HA_MODE_XFER) {
+ if (softc->ha_mode == CTL_HA_MODE_XFER) {
const struct ctl_cmd_entry *entry;
entry = ctl_get_cmd_entry(&io->scsiio, NULL);
@@ -852,11 +851,11 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
* mode
*/
case CTL_MSG_FINISH_IO:
- if (ctl_softc->ha_mode == CTL_HA_MODE_XFER)
- ctl_isc_handler_finish_xfer(ctl_softc,
+ if (softc->ha_mode == CTL_HA_MODE_XFER)
+ ctl_isc_handler_finish_xfer(softc,
&msg_info);
else
- ctl_isc_handler_finish_ser_only(ctl_softc,
+ ctl_isc_handler_finish_ser_only(softc,
&msg_info);
break;
@@ -886,7 +885,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
case CTL_MSG_MANAGE_TASKS: {
struct ctl_taskio *taskio;
taskio = (struct ctl_taskio *)ctl_alloc_io_nowait(
- ctl_softc->othersc_pool);
+ softc->othersc_pool);
if (taskio == NULL) {
printf("ctl_isc_event_handler: can't allocate "
"ctl_io!\n");
@@ -915,7 +914,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
/* Persistent Reserve action which needs attention */
case CTL_MSG_PERS_ACTION:
presio = (struct ctl_prio *)ctl_alloc_io_nowait(
- ctl_softc->othersc_pool);
+ softc->othersc_pool);
if (presio == NULL) {
printf("ctl_isc_event_handler: can't allocate "
"ctl_io!\n");
@@ -1744,8 +1743,8 @@ ctl_ioctl_do_datamove(struct ctl_scsiio *ctsio)
i < ext_sg_entries && j < kern_sg_entries;) {
uint8_t *ext_ptr, *kern_ptr;
- len_to_copy = ctl_min(ext_sglist[i].len - ext_watermark,
- kern_sglist[j].len - kern_watermark);
+ len_to_copy = MIN(ext_sglist[i].len - ext_watermark,
+ kern_sglist[j].len - kern_watermark);
ext_ptr = (uint8_t *)ext_sglist[i].addr;
ext_ptr = ext_ptr + ext_watermark;
@@ -1832,16 +1831,16 @@ bailout:
static int
ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
union ctl_ha_msg msg_info;
struct ctl_lun *lun;
int retval = 0;
uint32_t targ_lun;
- ctl_softc = control_softc;
+ softc = control_softc;
targ_lun = ctsio->io_hdr.nexus.targ_mapped_lun;
- lun = ctl_softc->ctl_luns[targ_lun];
+ lun = softc->ctl_luns[targ_lun];
if (lun==NULL)
{
/*
@@ -1886,7 +1885,7 @@ ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
break;
case CTL_ACTION_PASS:
case CTL_ACTION_SKIP:
- if (ctl_softc->ha_mode == CTL_HA_MODE_XFER) {
+ if (softc->ha_mode == CTL_HA_MODE_XFER) {
ctsio->io_hdr.flags |= CTL_FLAG_IS_WAS_ON_RTR;
ctl_enqueue_rtr((union ctl_io *)ctsio);
} else {
@@ -2835,8 +2834,8 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
bbr_info->scsi_status = metatask->taskinfo.bbrread.scsi_status;
memcpy(&bbr_info->sense_data,
&metatask->taskinfo.bbrread.sense_data,
- ctl_min(sizeof(bbr_info->sense_data),
- sizeof(metatask->taskinfo.bbrread.sense_data)));
+ MIN(sizeof(bbr_info->sense_data),
+ sizeof(metatask->taskinfo.bbrread.sense_data)));
cfi_free_metatask(metatask);
@@ -3498,11 +3497,11 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (port->wwpn_iid[j].name != NULL)
retval = sbuf_printf(sb,
- "\t<initiator>%u %s</initiator>\n",
+ "\t<initiator id=\"%u\">%s</initiator>\n",
j, port->wwpn_iid[j].name);
else
retval = sbuf_printf(sb,
- "\t<initiator>%u naa.%08jx</initiator>\n",
+ "\t<initiator id=\"%u\">naa.%08jx</initiator>\n",
j, port->wwpn_iid[j].wwpn);
if (retval != 0)
break;
@@ -3602,11 +3601,11 @@ ctl_port_idx(int port_num)
}
static uint32_t
-ctl_map_lun(int port_num, uint32_t lun_id)
+ctl_map_lun(struct ctl_softc *softc, int port_num, uint32_t lun_id)
{
struct ctl_port *port;
- port = control_softc->ctl_ports[ctl_port_idx(port_num)];
+ port = softc->ctl_ports[ctl_port_idx(port_num)];
if (port == NULL)
return (UINT32_MAX);
if (port->lun_map == NULL)
@@ -3615,12 +3614,12 @@ ctl_map_lun(int port_num, uint32_t lun_id)
}
static uint32_t
-ctl_map_lun_back(int port_num, uint32_t lun_id)
+ctl_map_lun_back(struct ctl_softc *softc, int port_num, uint32_t lun_id)
{
struct ctl_port *port;
uint32_t i;
- port = control_softc->ctl_ports[ctl_port_idx(port_num)];
+ port = softc->ctl_ports[ctl_port_idx(port_num)];
if (port->lun_map == NULL)
return (lun_id);
for (i = 0; i < CTL_MAX_LUNS; i++) {
@@ -3643,7 +3642,7 @@ ctl_ffz(uint32_t *mask, uint32_t size)
num_chunks = (size >> 5);
if (num_chunks == 0)
num_chunks++;
- num_pieces = ctl_min((sizeof(uint32_t) * 8), size);
+ num_pieces = MIN((sizeof(uint32_t) * 8), size);
for (i = 0; i < num_chunks; i++) {
for (j = 0; j < num_pieces; j++) {
@@ -3890,7 +3889,7 @@ ctl_copy_io(union ctl_io *src, union ctl_io *dest)
*/
pool_ref = dest->io_hdr.pool;
- memcpy(dest, src, ctl_min(sizeof(*src), sizeof(*dest)));
+ memcpy(dest, src, MIN(sizeof(*src), sizeof(*dest)));
dest->io_hdr.pool = pool_ref;
/*
@@ -4777,25 +4776,25 @@ ctl_free_lun(struct ctl_lun *lun)
static void
ctl_create_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
- ctl_softc = control_softc;
+ softc = control_softc;
/*
* ctl_alloc_lun() should handle all potential failure cases.
*/
- ctl_alloc_lun(ctl_softc, NULL, be_lun, ctl_softc->target);
+ ctl_alloc_lun(softc, NULL, be_lun, softc->target);
}
int
ctl_add_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc = control_softc;
+ struct ctl_softc *softc = control_softc;
- mtx_lock(&ctl_softc->ctl_lock);
- STAILQ_INSERT_TAIL(&ctl_softc->pending_lun_queue, be_lun, links);
- mtx_unlock(&ctl_softc->ctl_lock);
- wakeup(&ctl_softc->pending_lun_queue);
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_INSERT_TAIL(&softc->pending_lun_queue, be_lun, links);
+ mtx_unlock(&softc->ctl_lock);
+ wakeup(&softc->pending_lun_queue);
return (0);
}
@@ -4803,16 +4802,15 @@ ctl_add_lun(struct ctl_be_lun *be_lun)
int
ctl_enable_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_port *port, *nport;
struct ctl_lun *lun;
int retval;
- ctl_softc = control_softc;
-
lun = (struct ctl_lun *)be_lun->ctl_lun;
+ softc = lun->ctl_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
mtx_lock(&lun->lun_lock);
if ((lun->flags & CTL_LUN_DISABLED) == 0) {
/*
@@ -4820,13 +4818,13 @@ ctl_enable_lun(struct ctl_be_lun *be_lun)
* enabled?
*/
mtx_unlock(&lun->lun_lock);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
lun->flags &= ~CTL_LUN_DISABLED;
mtx_unlock(&lun->lun_lock);
- for (port = STAILQ_FIRST(&ctl_softc->port_list); port != NULL; port = nport) {
+ for (port = STAILQ_FIRST(&softc->port_list); port != NULL; port = nport) {
nport = STAILQ_NEXT(port, links);
/*
@@ -4834,9 +4832,9 @@ ctl_enable_lun(struct ctl_be_lun *be_lun)
* This can lead to a callback into CTL (at least in the
* case of the internal initiator frontend.
*/
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
retval = port->lun_enable(port->targ_lun_arg, lun->target,lun->lun);
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
if (retval != 0) {
printf("%s: FETD %s port %d returned error "
"%d for lun_enable on target %ju lun %jd\n",
@@ -4851,7 +4849,7 @@ ctl_enable_lun(struct ctl_be_lun *be_lun)
#endif
}
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
@@ -4859,27 +4857,26 @@ ctl_enable_lun(struct ctl_be_lun *be_lun)
int
ctl_disable_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_port *port;
struct ctl_lun *lun;
int retval;
- ctl_softc = control_softc;
-
lun = (struct ctl_lun *)be_lun->ctl_lun;
+ softc = lun->ctl_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
mtx_lock(&lun->lun_lock);
if (lun->flags & CTL_LUN_DISABLED) {
mtx_unlock(&lun->lun_lock);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
lun->flags |= CTL_LUN_DISABLED;
mtx_unlock(&lun->lun_lock);
- STAILQ_FOREACH(port, &ctl_softc->port_list, links) {
- mtx_unlock(&ctl_softc->ctl_lock);
+ STAILQ_FOREACH(port, &softc->port_list, links) {
+ mtx_unlock(&softc->ctl_lock);
/*
* Drop the lock before we call the frontend's disable
* routine, to avoid lock order reversals.
@@ -4889,7 +4886,7 @@ ctl_disable_lun(struct ctl_be_lun *be_lun)
*/
retval = port->lun_disable(port->targ_lun_arg, lun->target,
lun->lun);
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
if (retval != 0) {
printf("ctl_alloc_lun: FETD %s port %d returned error "
"%d for lun_disable on target %ju lun %jd\n",
@@ -4898,7 +4895,7 @@ ctl_disable_lun(struct ctl_be_lun *be_lun)
}
}
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
@@ -4906,80 +4903,55 @@ ctl_disable_lun(struct ctl_be_lun *be_lun)
int
ctl_start_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
-
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags &= ~CTL_LUN_STOPPED;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
int
ctl_stop_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
-
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags |= CTL_LUN_STOPPED;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
int
ctl_lun_offline(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
-
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags |= CTL_LUN_OFFLINE;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
int
ctl_lun_online(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
-
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags &= ~CTL_LUN_OFFLINE;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
int
ctl_invalidate_lun(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_lun *lun;
- ctl_softc = control_softc;
-
lun = (struct ctl_lun *)be_lun->ctl_lun;
+ softc = lun->ctl_softc;
mtx_lock(&lun->lun_lock);
@@ -5002,9 +4974,9 @@ ctl_invalidate_lun(struct ctl_be_lun *be_lun)
*/
if (TAILQ_EMPTY(&lun->ooa_queue)) {
mtx_unlock(&lun->lun_lock);
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
ctl_free_lun(lun);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
} else
mtx_unlock(&lun->lun_lock);
@@ -5014,32 +4986,22 @@ ctl_invalidate_lun(struct ctl_be_lun *be_lun)
int
ctl_lun_inoperable(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags |= CTL_LUN_INOPERABLE;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
int
ctl_lun_operable(struct ctl_be_lun *be_lun)
{
- struct ctl_softc *ctl_softc;
- struct ctl_lun *lun;
-
- ctl_softc = control_softc;
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
lun->flags &= ~CTL_LUN_INOPERABLE;
mtx_unlock(&lun->lun_lock);
-
return (0);
}
@@ -5225,7 +5187,6 @@ int
ctl_scsi_release(struct ctl_scsiio *ctsio)
{
int length, longid, thirdparty_id, resv_id;
- struct ctl_softc *ctl_softc;
struct ctl_lun *lun;
uint32_t residx;
@@ -5236,7 +5197,6 @@ ctl_scsi_release(struct ctl_scsiio *ctsio)
residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- ctl_softc = control_softc;
switch (ctsio->cdb[0]) {
case RELEASE_10: {
@@ -5313,7 +5273,6 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio)
int extent, thirdparty, longid;
int resv_id, length;
uint64_t thirdparty_id;
- struct ctl_softc *ctl_softc;
struct ctl_lun *lun;
uint32_t residx;
@@ -5328,7 +5287,6 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio)
residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- ctl_softc = control_softc;
switch (ctsio->cdb[0]) {
case RESERVE_10: {
@@ -5402,13 +5360,11 @@ ctl_start_stop(struct ctl_scsiio *ctsio)
{
struct scsi_start_stop_unit *cdb;
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
int retval;
CTL_DEBUG_PRINT(("ctl_start_stop\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- ctl_softc = control_softc;
retval = 0;
cdb = (struct scsi_start_stop_unit *)ctsio->cdb;
@@ -5529,7 +5485,7 @@ int
ctl_sync_cache(struct ctl_scsiio *ctsio)
{
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
uint64_t starting_lba;
uint32_t block_count;
int retval;
@@ -5537,7 +5493,7 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_sync_cache\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- ctl_softc = control_softc;
+ softc = lun->ctl_softc;
retval = 0;
switch (ctsio->cdb[0]) {
@@ -5590,7 +5546,7 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
* CACHE command directly to the back end.
*/
mtx_lock(&lun->lun_lock);
- if ((ctl_softc->flags & CTL_FLAG_REAL_SYNC)
+ if ((softc->flags & CTL_FLAG_REAL_SYNC)
&& (++(lun->sync_count) >= lun->sync_interval)) {
lun->sync_count = 0;
mtx_unlock(&lun->lun_lock);
@@ -5611,13 +5567,11 @@ ctl_format(struct ctl_scsiio *ctsio)
{
struct scsi_format *cdb;
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
int length, defect_list_len;
CTL_DEBUG_PRINT(("ctl_format\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- ctl_softc = control_softc;
cdb = (struct scsi_format *)ctsio->cdb;
@@ -6075,7 +6029,6 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
{
struct scsi_control_page *current_cp, *saved_cp, *user_cp;
struct ctl_lun *lun;
- struct ctl_softc *softc;
int set_ua;
uint32_t initidx;
@@ -6091,8 +6044,6 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
(page_index->page_data + (page_index->page_len *
CTL_PAGE_SAVED));
- softc = control_softc;
-
mtx_lock(&lun->lun_lock);
if (((current_cp->rlec & SCP_DSENSE) == 0)
&& ((user_cp->rlec & SCP_DSENSE) != 0)) {
@@ -6801,7 +6752,7 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
header = (struct scsi_mode_hdr_6 *)ctsio->kern_data_ptr;
- header->datalen = ctl_min(total_len - 1, 254);
+ header->datalen = MIN(total_len - 1, 254);
if (control_dev == 0) {
header->dev_specific = 0x10; /* DPOFUA */
if ((lun->flags & CTL_LUN_READONLY) ||
@@ -6823,7 +6774,7 @@ ctl_mode_sense(struct ctl_scsiio *ctsio)
header = (struct scsi_mode_hdr_10 *)ctsio->kern_data_ptr;
- datalen = ctl_min(total_len - 2, 65533);
+ datalen = MIN(total_len - 2, 65533);
scsi_ulto2b(datalen, header->datalen);
if (control_dev == 0) {
header->dev_specific = 0x10; /* DPOFUA */
@@ -7358,8 +7309,8 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_report_tagret_port_groups\n"));
cdb = (struct scsi_maintenance_in *)ctsio->cdb;
- softc = control_softc;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ softc = lun->ctl_softc;
retval = CTL_RETVAL_COMPLETE;
@@ -7390,7 +7341,8 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
STAILQ_FOREACH(port, &softc->port_list, links) {
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
continue;
- if (ctl_map_lun_back(port->targ_port, lun->lun) >= CTL_MAX_LUNS)
+ if (ctl_map_lun_back(softc, port->targ_port, lun->lun) >=
+ CTL_MAX_LUNS)
continue;
num_target_ports++;
}
@@ -7463,8 +7415,8 @@ ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
STAILQ_FOREACH(port, &softc->port_list, links) {
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
continue;
- if (ctl_map_lun_back(port->targ_port, lun->lun) >=
- CTL_MAX_LUNS)
+ if (ctl_map_lun_back(softc, port->targ_port, lun->lun)
+ >= CTL_MAX_LUNS)
continue;
p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
scsi_ulto2b(p, tpg_desc->descriptors[pc].
@@ -7756,13 +7708,12 @@ ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_persistent_reserve_in\n"));
- softc = control_softc;
-
cdb = (struct scsi_per_res_in *)ctsio->cdb;
alloc_len = scsi_2btoul(cdb->length);
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ softc = lun->ctl_softc;
retry:
mtx_lock(&lun->lun_lock);
@@ -8385,10 +8336,9 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
retval = CTL_RETVAL_COMPLETE;
- softc = control_softc;
-
cdb = (struct scsi_per_res_out *)ctsio->cdb;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ softc = lun->ctl_softc;
/*
* We only support whole-LUN scope. The scope & type are ignored for
@@ -9304,6 +9254,7 @@ ctl_verify(struct ctl_scsiio *ctsio)
int
ctl_report_luns(struct ctl_scsiio *ctsio)
{
+ struct ctl_softc *softc = control_softc;
struct scsi_report_luns *cdb;
struct scsi_report_luns_data *lun_data;
struct ctl_lun *lun, *request_lun;
@@ -9319,9 +9270,9 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_report_luns\n"));
- mtx_lock(&control_softc->ctl_lock);
- num_luns = control_softc->num_luns;
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
+ num_luns = softc->num_luns;
+ mtx_unlock(&softc->ctl_lock);
switch (cdb->select_report) {
case RPL_REPORT_DEFAULT:
@@ -9373,12 +9324,13 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
initidx = ctl_get_initindex(&ctsio->io_hdr.nexus);
- mtx_lock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
for (targ_lun_id = 0, num_filled = 0; targ_lun_id < CTL_MAX_LUNS && num_filled < num_luns; targ_lun_id++) {
- lun_id = ctl_map_lun(ctsio->io_hdr.nexus.targ_port, targ_lun_id);
+ lun_id = ctl_map_lun(softc, ctsio->io_hdr.nexus.targ_port,
+ targ_lun_id);
if (lun_id >= CTL_MAX_LUNS)
continue;
- lun = control_softc->ctl_luns[lun_id];
+ lun = softc->ctl_luns[lun_id];
if (lun == NULL)
continue;
@@ -9434,7 +9386,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
mtx_unlock(&lun->lun_lock);
}
}
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
/*
* It's quite possible that we've returned fewer LUNs than we allocated
@@ -9563,7 +9515,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
(struct scsi_sense_data_fixed *)sense_ptr);
else
memcpy(sense_ptr, &lun->pending_sense[initidx],
- ctl_min(sizeof(*sense_ptr),
+ MIN(sizeof(*sense_ptr),
sizeof(lun->pending_sense[initidx])));
ctl_clear_mask(lun->have_ca, initidx);
@@ -9647,6 +9599,7 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
struct scsi_vpd_supported_pages *pages;
int sup_page_size;
struct ctl_lun *lun;
+ int p;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
@@ -9680,27 +9633,30 @@ ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
else
pages->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
- pages->length = SCSI_EVPD_NUM_SUPPORTED_PAGES;
+ p = 0;
/* Supported VPD pages */
- pages->page_list[0] = SVPD_SUPPORTED_PAGES;
+ pages->page_list[p++] = SVPD_SUPPORTED_PAGES;
/* Serial Number */
- pages->page_list[1] = SVPD_UNIT_SERIAL_NUMBER;
+ pages->page_list[p++] = SVPD_UNIT_SERIAL_NUMBER;
/* Device Identification */
- pages->page_list[2] = SVPD_DEVICE_ID;
+ pages->page_list[p++] = SVPD_DEVICE_ID;
/* Extended INQUIRY Data */
- pages->page_list[3] = SVPD_EXTENDED_INQUIRY_DATA;
+ pages->page_list[p++] = SVPD_EXTENDED_INQUIRY_DATA;
/* Mode Page Policy */
- pages->page_list[4] = SVPD_MODE_PAGE_POLICY;
+ pages->page_list[p++] = SVPD_MODE_PAGE_POLICY;
/* SCSI Ports */
- pages->page_list[5] = SVPD_SCSI_PORTS;
+ pages->page_list[p++] = SVPD_SCSI_PORTS;
/* Third-party Copy */
- pages->page_list[6] = SVPD_SCSI_TPC;
- /* Block limits */
- pages->page_list[7] = SVPD_BLOCK_LIMITS;
- /* Block Device Characteristics */
- pages->page_list[8] = SVPD_BDC;
- /* Logical Block Provisioning */
- pages->page_list[9] = SVPD_LBP;
+ pages->page_list[p++] = SVPD_SCSI_TPC;
+ if (lun != NULL && lun->be_lun->lun_type == T_DIRECT) {
+ /* Block limits */
+ pages->page_list[p++] = SVPD_BLOCK_LIMITS;
+ /* Block Device Characteristics */
+ pages->page_list[p++] = SVPD_BDC;
+ /* Logical Block Provisioning */
+ pages->page_list[p++] = SVPD_LBP;
+ }
+ pages->length = p;
ctl_set_success(ctsio);
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
@@ -9869,15 +9825,15 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
{
struct scsi_vpd_device_id *devid_ptr;
struct scsi_vpd_id_descriptor *desc;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_lun *lun;
struct ctl_port *port;
int data_len;
uint8_t proto;
- ctl_softc = control_softc;
+ softc = control_softc;
- port = ctl_softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
+ port = softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
data_len = sizeof(struct scsi_vpd_device_id) +
@@ -10011,7 +9967,7 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
continue;
if (lun != NULL &&
- ctl_map_lun_back(port->targ_port, lun->lun) >=
+ ctl_map_lun_back(softc, port->targ_port, lun->lun) >=
CTL_MAX_LUNS)
continue;
num_target_ports++;
@@ -10065,8 +10021,8 @@ ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
continue;
if (lun != NULL &&
- ctl_map_lun_back(port->targ_port, lun->lun) >=
- CTL_MAX_LUNS)
+ ctl_map_lun_back(softc, port->targ_port, lun->lun)
+ >= CTL_MAX_LUNS)
continue;
p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
scsi_ulto2b(p, pd->relative_port_id);
@@ -10142,7 +10098,7 @@ ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
scsi_ulto4b(0xffffffff, bl_ptr->max_txfer_len);
if (lun != NULL) {
bs = lun->be_lun->blocksize;
- scsi_ulto4b(MAXPHYS / bs, bl_ptr->opt_txfer_len);
+ scsi_ulto4b(lun->be_lun->opttxferlen, bl_ptr->opt_txfer_len);
if (lun->be_lun->flags & CTL_LUN_FLAG_UNMAP) {
scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_lba_cnt);
scsi_ulto4b(0xffffffff, bl_ptr->max_unmap_blk_cnt);
@@ -10282,13 +10238,12 @@ ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
static int
ctl_inquiry_evpd(struct ctl_scsiio *ctsio)
{
+ struct ctl_lun *lun;
struct scsi_inquiry *cdb;
int alloc_len, retval;
+ lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
cdb = (struct scsi_inquiry *)ctsio->cdb;
-
- retval = CTL_RETVAL_COMPLETE;
-
alloc_len = scsi_2btoul(cdb->length);
switch (cdb->page_code) {
@@ -10314,15 +10269,22 @@ ctl_inquiry_evpd(struct ctl_scsiio *ctsio)
retval = ctl_inquiry_evpd_tpc(ctsio, alloc_len);
break;
case SVPD_BLOCK_LIMITS:
+ if (lun == NULL || lun->be_lun->lun_type != T_DIRECT)
+ goto err;
retval = ctl_inquiry_evpd_block_limits(ctsio, alloc_len);
break;
case SVPD_BDC:
+ if (lun == NULL || lun->be_lun->lun_type != T_DIRECT)
+ goto err;
retval = ctl_inquiry_evpd_bdc(ctsio, alloc_len);
break;
case SVPD_LBP:
+ if (lun == NULL || lun->be_lun->lun_type != T_DIRECT)
+ goto err;
retval = ctl_inquiry_evpd_lbp(ctsio, alloc_len);
break;
default:
+err:
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
@@ -10342,20 +10304,20 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
{
struct scsi_inquiry_data *inq_ptr;
struct scsi_inquiry *cdb;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_lun *lun;
char *val;
uint32_t alloc_len, data_len;
ctl_port_type port_type;
- ctl_softc = control_softc;
+ softc = control_softc;
/*
* Figure out whether we're talking to a Fibre Channel port or not.
* We treat the ioctl front end, and any SCSI adapters, as packetized
* SCSI front ends.
*/
- port_type = ctl_softc->ctl_ports[
+ port_type = softc->ctl_ports[
ctl_port_idx(ctsio->io_hdr.nexus.targ_port)]->port_type;
if (port_type == CTL_PORT_IOCTL || port_type == CTL_PORT_INTERNAL)
port_type = CTL_PORT_SCSI;
@@ -10432,7 +10394,7 @@ ctl_inquiry_std(struct ctl_scsiio *ctsio)
if (lun != NULL)
inq_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
lun->be_lun->lun_type;
- else if (ctl_softc->inquiry_pq_no_lun == 0)
+ else if (softc->inquiry_pq_no_lun == 0)
inq_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
else
inq_ptr->device = (SID_QUAL_BAD_LU << 5) | T_NODEVICE;
@@ -11065,7 +11027,6 @@ ctl_check_blocked(struct ctl_lun *lun)
break;
case CTL_ACTION_PASS:
case CTL_ACTION_SKIP: {
- struct ctl_softc *softc;
const struct ctl_cmd_entry *entry;
int isc_retval;
@@ -11104,7 +11065,6 @@ ctl_check_blocked(struct ctl_lun *lun)
break;
}
entry = ctl_get_cmd_entry(&cur_blocked->scsiio, NULL);
- softc = control_softc;
/*
* Check this I/O for LUN state changes that may
@@ -11114,7 +11074,7 @@ ctl_check_blocked(struct ctl_lun *lun)
* for any states that can be caused by SCSI
* commands.
*/
- if (ctl_scsiio_lun_check(softc, lun, entry,
+ if (ctl_scsiio_lun_check(lun, entry,
&cur_blocked->scsiio) == 0) {
cur_blocked->io_hdr.flags |=
CTL_FLAG_IS_WAS_ON_RTR;
@@ -11148,9 +11108,10 @@ ctl_check_blocked(struct ctl_lun *lun)
* careful attention to the placement of any new checks.
*/
static int
-ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
+ctl_scsiio_lun_check(struct ctl_lun *lun,
const struct ctl_cmd_entry *entry, struct ctl_scsiio *ctsio)
{
+ struct ctl_softc *softc = lun->ctl_softc;
int retval;
uint32_t residx;
@@ -11162,7 +11123,7 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
* If this shelf is a secondary shelf controller, we have to reject
* any media access commands.
*/
- if ((ctl_softc->flags & CTL_FLAG_ACTIVE_SHELF) == 0 &&
+ if ((softc->flags & CTL_FLAG_ACTIVE_SHELF) == 0 &&
(entry->flags & CTL_CMD_FLAG_OK_ON_SECONDARY) == 0) {
ctl_set_lun_standby(ctsio);
retval = 1;
@@ -11268,14 +11229,14 @@ static void
ctl_failover(void)
{
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
union ctl_io *next_io, *pending_io;
union ctl_io *io;
int lun_idx;
- ctl_softc = control_softc;
+ softc = control_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
/*
* Remove any cmds from the other SC from the rtr queue. These
* will obviously only be for LUNs for which we're the primary.
@@ -11285,19 +11246,19 @@ ctl_failover(void)
* which HA mode we're in.
*/
#ifdef notyet
- mtx_lock(&ctl_softc->queue_lock);
- for (io = (union ctl_io *)STAILQ_FIRST(&ctl_softc->rtr_queue);
+ mtx_lock(&softc->queue_lock);
+ for (io = (union ctl_io *)STAILQ_FIRST(&softc->rtr_queue);
io != NULL; io = next_io) {
next_io = (union ctl_io *)STAILQ_NEXT(&io->io_hdr, links);
if (io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)
- STAILQ_REMOVE(&ctl_softc->rtr_queue, &io->io_hdr,
+ STAILQ_REMOVE(&softc->rtr_queue, &io->io_hdr,
ctl_io_hdr, links);
}
- mtx_unlock(&ctl_softc->queue_lock);
+ mtx_unlock(&softc->queue_lock);
#endif
- for (lun_idx=0; lun_idx < ctl_softc->num_luns; lun_idx++) {
- lun = ctl_softc->ctl_luns[lun_idx];
+ for (lun_idx=0; lun_idx < softc->num_luns; lun_idx++) {
+ lun = softc->ctl_luns[lun_idx];
if (lun==NULL)
continue;
@@ -11309,7 +11270,7 @@ ctl_failover(void)
continue;
if ((lun->flags & CTL_LUN_PRIMARY_SC)
- && (ctl_softc->ha_mode == CTL_HA_MODE_SER_ONLY)) {
+ && (softc->ha_mode == CTL_HA_MODE_SER_ONLY)) {
printf("FAILOVER: primary lun %d\n", lun_idx);
/*
* Remove all commands from the other SC. First from the
@@ -11351,7 +11312,7 @@ ctl_failover(void)
}
ctl_check_blocked(lun);
} else if ((lun->flags & CTL_LUN_PRIMARY_SC)
- && (ctl_softc->ha_mode == CTL_HA_MODE_XFER)) {
+ && (softc->ha_mode == CTL_HA_MODE_XFER)) {
printf("FAILOVER: primary lun %d\n", lun_idx);
/*
@@ -11369,7 +11330,7 @@ ctl_failover(void)
io->io_hdr.flags |= CTL_FLAG_ABORT;
}
} else if (((lun->flags & CTL_LUN_PRIMARY_SC) == 0)
- && (ctl_softc->ha_mode == CTL_HA_MODE_XFER)) {
+ && (softc->ha_mode == CTL_HA_MODE_XFER)) {
printf("FAILOVER: secondary lun %d\n", lun_idx);
@@ -11408,7 +11369,7 @@ ctl_failover(void)
ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
} else if (((lun->flags & CTL_LUN_PRIMARY_SC) == 0)
- && (ctl_softc->ha_mode == CTL_HA_MODE_SER_ONLY)) {
+ && (softc->ha_mode == CTL_HA_MODE_SER_ONLY)) {
printf("FAILOVER: secondary lun %d\n", lun_idx);
/*
* if the first io on the OOA is not on the RtR queue
@@ -11498,15 +11459,15 @@ ctl_failover(void)
ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
} else {
panic("Unhandled HA mode failover, LUN flags = %#x, "
- "ha_mode = #%x", lun->flags, ctl_softc->ha_mode);
+ "ha_mode = #%x", lun->flags, softc->ha_mode);
}
}
ctl_pause_rtr = 0;
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
}
static int
-ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
+ctl_scsiio_precheck(struct ctl_softc *softc, struct ctl_scsiio *ctsio)
{
struct ctl_lun *lun;
const struct ctl_cmd_entry *entry;
@@ -11519,7 +11480,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
targ_lun = ctsio->io_hdr.nexus.targ_mapped_lun;
if ((targ_lun < CTL_MAX_LUNS)
- && ((lun = ctl_softc->ctl_luns[targ_lun]) != NULL)) {
+ && ((lun = softc->ctl_luns[targ_lun]) != NULL)) {
/*
* If the LUN is invalid, pretend that it doesn't exist.
* It will go away as soon as all pending I/O has been
@@ -11651,7 +11612,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
}
- if (ctl_scsiio_lun_check(ctl_softc, lun, entry, ctsio) != 0) {
+ if (ctl_scsiio_lun_check(lun, entry, ctsio) != 0) {
mtx_unlock(&lun->lun_lock);
ctl_done((union ctl_io *)ctsio);
return (retval);
@@ -11859,13 +11820,13 @@ bailout:
* our single target.
*/
static int
-ctl_bus_reset(struct ctl_softc *ctl_softc, union ctl_io *io)
+ctl_bus_reset(struct ctl_softc *softc, union ctl_io *io)
{
- return(ctl_target_reset(ctl_softc, io, CTL_UA_BUS_RESET));
+ return(ctl_target_reset(softc, io, CTL_UA_BUS_RESET));
}
static int
-ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
+ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
ctl_ua_type ua_type)
{
struct ctl_lun *lun;
@@ -11889,10 +11850,10 @@ ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
}
retval = 0;
- mtx_lock(&ctl_softc->ctl_lock);
- STAILQ_FOREACH(lun, &ctl_softc->lun_list, links)
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_FOREACH(lun, &softc->lun_list, links)
retval += ctl_lun_reset(lun, io, ua_type);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (retval);
}
@@ -12078,7 +12039,7 @@ ctl_abort_task(union ctl_io *io)
{
union ctl_io *xio;
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
#if 0
struct sbuf sb;
char printbuf[128];
@@ -12086,19 +12047,19 @@ ctl_abort_task(union ctl_io *io)
int found;
uint32_t targ_lun;
- ctl_softc = control_softc;
+ softc = control_softc;
found = 0;
/*
* Look up the LUN.
*/
targ_lun = io->io_hdr.nexus.targ_mapped_lun;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
if ((targ_lun < CTL_MAX_LUNS)
- && (ctl_softc->ctl_luns[targ_lun] != NULL))
- lun = ctl_softc->ctl_luns[targ_lun];
+ && (softc->ctl_luns[targ_lun] != NULL))
+ lun = softc->ctl_luns[targ_lun];
else {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (1);
}
@@ -12108,7 +12069,7 @@ ctl_abort_task(union ctl_io *io)
#endif
mtx_lock(&lun->lun_lock);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
/*
* Run through the OOA queue and attempt to find the given I/O.
* The target port, initiator ID, tag type and tag number have to
@@ -12224,7 +12185,7 @@ ctl_abort_task(union ctl_io *io)
static void
ctl_run_task(union ctl_io *io)
{
- struct ctl_softc *ctl_softc = control_softc;
+ struct ctl_softc *softc = control_softc;
int retval = 1;
const char *task_desc;
@@ -12279,12 +12240,12 @@ ctl_run_task(union ctl_io *io)
uint32_t targ_lun;
targ_lun = io->io_hdr.nexus.targ_mapped_lun;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
if ((targ_lun < CTL_MAX_LUNS)
- && (ctl_softc->ctl_luns[targ_lun] != NULL))
- lun = ctl_softc->ctl_luns[targ_lun];
+ && (softc->ctl_luns[targ_lun] != NULL))
+ lun = softc->ctl_luns[targ_lun];
else {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
retval = 1;
break;
}
@@ -12311,14 +12272,14 @@ ctl_run_task(union ctl_io *io)
retval = ctl_lun_reset(lun, io,
CTL_UA_LUN_RESET);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
break;
}
case CTL_TASK_TARGET_RESET:
- retval = ctl_target_reset(ctl_softc, io, CTL_UA_TARG_RESET);
+ retval = ctl_target_reset(softc, io, CTL_UA_TARG_RESET);
break;
case CTL_TASK_BUS_RESET:
- retval = ctl_bus_reset(ctl_softc, io);
+ retval = ctl_bus_reset(softc, io);
break;
case CTL_TASK_PORT_LOGIN:
break;
@@ -12345,13 +12306,13 @@ ctl_handle_isc(union ctl_io *io)
{
int free_io;
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
uint32_t targ_lun;
- ctl_softc = control_softc;
+ softc = control_softc;
targ_lun = io->io_hdr.nexus.targ_mapped_lun;
- lun = ctl_softc->ctl_luns[targ_lun];
+ lun = softc->ctl_luns[targ_lun];
switch (io->io_hdr.msg_type) {
case CTL_MSG_SERIALIZE:
@@ -12366,7 +12327,7 @@ ctl_handle_isc(union ctl_io *io)
free_io = 0;
entry = ctl_get_cmd_entry(&io->scsiio, NULL);
mtx_lock(&lun->lun_lock);
- if (ctl_scsiio_lun_check(ctl_softc, lun,
+ if (ctl_scsiio_lun_check(lun,
entry, (struct ctl_scsiio *)io) != 0) {
mtx_unlock(&lun->lun_lock);
ctl_done(io);
@@ -12378,7 +12339,7 @@ ctl_handle_isc(union ctl_io *io)
break;
}
case CTL_MSG_FINISH_IO:
- if (ctl_softc->ha_mode == CTL_HA_MODE_XFER) {
+ if (softc->ha_mode == CTL_HA_MODE_XFER) {
free_io = 0;
ctl_done(io);
} else {
@@ -12523,8 +12484,8 @@ ctl_inject_error(struct ctl_lun *lun, union ctl_io *io)
* checks.
*/
bcopy(&desc->custom_sense, &io->scsiio.sense_data,
- ctl_min(sizeof(desc->custom_sense),
- sizeof(io->scsiio.sense_data)));
+ MIN(sizeof(desc->custom_sense),
+ sizeof(io->scsiio.sense_data)));
io->scsiio.scsi_status = SCSI_STATUS_CHECK_COND;
io->scsiio.sense_len = SSD_FULL_SIZE;
io->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE;
@@ -12753,7 +12714,7 @@ ctl_datamove(union ctl_io *io)
*/
for (sg_entries_sent = 0; sg_entries_sent <
msg.dt.kern_sg_entries; msg.dt.sg_sequence++) {
- msg.dt.cur_sg_entries = ctl_min((sizeof(msg.dt.sg_list)/
+ msg.dt.cur_sg_entries = MIN((sizeof(msg.dt.sg_list)/
sizeof(msg.dt.sg_list[0])),
msg.dt.kern_sg_entries - sg_entries_sent);
@@ -13116,7 +13077,7 @@ ctl_datamove_remote_sgl_setup(union ctl_io *io)
for (i = 0; (i < sizeof(io->io_hdr.remote_sglist) /
sizeof(io->io_hdr.remote_sglist[0])) &&
(len_to_go > 0); i++) {
- local_sglist[i].len = ctl_min(len_to_go, 131072);
+ local_sglist[i].len = MIN(len_to_go, 131072);
CTL_SIZE_8B(local_dma_sglist[i].len,
local_sglist[i].len);
local_sglist[i].addr =
@@ -13252,8 +13213,8 @@ ctl_datamove_remote_xfer(union ctl_io *io, unsigned command,
* also have enough slack left over at the end, though,
* to round up to the next 8 byte boundary.
*/
- cur_len = ctl_min(local_sglist[i].len - local_used,
- remote_sglist[j].len - remote_used);
+ cur_len = MIN(local_sglist[i].len - local_used,
+ remote_sglist[j].len - remote_used);
/*
* In this case, we have a size issue and need to decrease
@@ -13477,14 +13438,13 @@ static int
ctl_process_done(union ctl_io *io)
{
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc = control_softc;
+ struct ctl_softc *softc = control_softc;
void (*fe_done)(union ctl_io *io);
uint32_t targ_port = ctl_port_idx(io->io_hdr.nexus.targ_port);
CTL_DEBUG_PRINT(("ctl_process_done\n"));
- fe_done =
- control_softc->ctl_ports[targ_port]->fe_done;
+ fe_done = softc->ctl_ports[targ_port]->fe_done;
#ifdef CTL_TIME_IO
if ((time_uptime - io->io_hdr.start_time) > ctl_time_io_secs) {
@@ -13611,9 +13571,9 @@ ctl_process_done(union ctl_io *io)
if ((lun->flags & CTL_LUN_INVALID)
&& TAILQ_EMPTY(&lun->ooa_queue)) {
mtx_unlock(&lun->lun_lock);
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
ctl_free_lun(lun);
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
} else
mtx_unlock(&lun->lun_lock);
@@ -13665,7 +13625,7 @@ bailout:
* if the frontend comes back in in this context to queue
* something.
*/
- if ((ctl_softc->ha_mode == CTL_HA_MODE_XFER)
+ if ((softc->ha_mode == CTL_HA_MODE_XFER)
&& (io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
union ctl_ha_msg msg;
@@ -13713,10 +13673,10 @@ int
ctl_queue_sense(union ctl_io *io)
{
struct ctl_lun *lun;
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
uint32_t initidx, targ_lun;
- ctl_softc = control_softc;
+ softc = control_softc;
CTL_DEBUG_PRINT(("ctl_queue_sense\n"));
@@ -13727,17 +13687,17 @@ ctl_queue_sense(union ctl_io *io)
* things like an INQUIRY to a LUN that we don't have enabled. We
* can't deal with that right now.
*/
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
/*
* If we don't have a LUN for this, just toss the sense
* information.
*/
targ_lun = io->io_hdr.nexus.targ_lun;
- targ_lun = ctl_map_lun(io->io_hdr.nexus.targ_port, targ_lun);
+ targ_lun = ctl_map_lun(softc, io->io_hdr.nexus.targ_port, targ_lun);
if ((targ_lun < CTL_MAX_LUNS)
- && (ctl_softc->ctl_luns[targ_lun] != NULL))
- lun = ctl_softc->ctl_luns[targ_lun];
+ && (softc->ctl_luns[targ_lun] != NULL))
+ lun = softc->ctl_luns[targ_lun];
else
goto bailout;
@@ -13753,13 +13713,13 @@ ctl_queue_sense(union ctl_io *io)
}
memcpy(&lun->pending_sense[initidx], &io->scsiio.sense_data,
- ctl_min(sizeof(lun->pending_sense[initidx]),
+ MIN(sizeof(lun->pending_sense[initidx]),
sizeof(io->scsiio.sense_data)));
ctl_set_mask(lun->have_ca, initidx);
mtx_unlock(&lun->lun_lock);
bailout:
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
ctl_free_io(io);
@@ -13774,12 +13734,9 @@ bailout:
int
ctl_queue(union ctl_io *io)
{
- struct ctl_softc *ctl_softc;
CTL_DEBUG_PRINT(("ctl_queue cdb[0]=%02X\n", io->scsiio.cdb[0]));
- ctl_softc = control_softc;
-
#ifdef CTL_TIME_IO
io->io_hdr.start_time = time_uptime;
getbintime(&io->io_hdr.start_bt);
@@ -13787,7 +13744,8 @@ ctl_queue(union ctl_io *io)
/* Map FE-specific LUN ID into global one. */
io->io_hdr.nexus.targ_mapped_lun =
- ctl_map_lun(io->io_hdr.nexus.targ_port, io->io_hdr.nexus.targ_lun);
+ ctl_map_lun(control_softc, io->io_hdr.nexus.targ_port,
+ io->io_hdr.nexus.targ_lun);
switch (io->io_hdr.io_type) {
case CTL_IO_SCSI:
@@ -13818,9 +13776,6 @@ ctl_done_timer_wakeup(void *arg)
void
ctl_done(union ctl_io *io)
{
- struct ctl_softc *ctl_softc;
-
- ctl_softc = control_softc;
/*
* Enable this to catch duplicate completion issues.
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index ae6c583..9cf967c 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -40,7 +40,6 @@
#ifndef _CTL_H_
#define _CTL_H_
-#define ctl_min(x,y) (((x) < (y)) ? (x) : (y))
#define CTL_RETVAL_COMPLETE 0
#define CTL_RETVAL_QUEUED 1
#define CTL_RETVAL_ALLOCATED 2
diff --git a/sys/cam/ctl/ctl_backend.c b/sys/cam/ctl/ctl_backend.c
index 0e1a76c..cabecb7 100644
--- a/sys/cam/ctl/ctl_backend.c
+++ b/sys/cam/ctl/ctl_backend.c
@@ -66,33 +66,33 @@ extern struct ctl_softc *control_softc;
int
ctl_backend_register(struct ctl_backend_driver *be)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_backend_driver *be_tmp;
- ctl_softc = control_softc;
+ softc = control_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
/*
* Sanity check, make sure this isn't a duplicate registration.
*/
- STAILQ_FOREACH(be_tmp, &ctl_softc->be_list, links) {
+ STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
if (strcmp(be_tmp->name, be->name) == 0) {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (-1);
}
}
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
/*
* Call the backend's initialization routine.
*/
be->init();
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
- STAILQ_INSERT_TAIL(&ctl_softc->be_list, be, links);
+ STAILQ_INSERT_TAIL(&softc->be_list, be, links);
- ctl_softc->num_backends++;
+ softc->num_backends++;
/*
* Don't want to increment the usage count for internal consumers,
@@ -113,7 +113,7 @@ ctl_backend_register(struct ctl_backend_driver *be)
atomic_set(&be->num_luns, 0);
#endif
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
@@ -121,24 +121,24 @@ ctl_backend_register(struct ctl_backend_driver *be)
int
ctl_backend_deregister(struct ctl_backend_driver *be)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
- ctl_softc = control_softc;
+ softc = control_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
#if 0
if (atomic_read(&be->num_luns) != 0) {
#endif
/* XXX KDM fix this! */
if (be->num_luns != 0) {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (-1);
}
- STAILQ_REMOVE(&ctl_softc->be_list, be, ctl_backend_driver, links);
+ STAILQ_REMOVE(&softc->be_list, be, ctl_backend_driver, links);
- ctl_softc->num_backends--;
+ softc->num_backends--;
/* XXX KDM find a substitute for this? */
#if 0
@@ -146,7 +146,7 @@ ctl_backend_deregister(struct ctl_backend_driver *be)
MOD_DEC_USE_COUNT;
#endif
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
@@ -154,21 +154,21 @@ ctl_backend_deregister(struct ctl_backend_driver *be)
struct ctl_backend_driver *
ctl_backend_find(char *backend_name)
{
- struct ctl_softc *ctl_softc;
+ struct ctl_softc *softc;
struct ctl_backend_driver *be_tmp;
- ctl_softc = control_softc;
+ softc = control_softc;
- mtx_lock(&ctl_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
- STAILQ_FOREACH(be_tmp, &ctl_softc->be_list, links) {
+ STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
if (strcmp(be_tmp->name, backend_name) == 0) {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (be_tmp);
}
}
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (NULL);
}
diff --git a/sys/cam/ctl/ctl_backend.h b/sys/cam/ctl/ctl_backend.h
index 5e0af5c..93a530c 100644
--- a/sys/cam/ctl/ctl_backend.h
+++ b/sys/cam/ctl/ctl_backend.h
@@ -146,10 +146,16 @@ typedef void (*be_lun_config_t)(void *be_lun,
*
* pblockexp is the log2() of number of LBAs on the LUN per physical sector.
*
- * pblockoff is the lowest LBA on the LUN aligned ot physical sector.
+ * pblockoff is the lowest LBA on the LUN aligned to physical sector.
+ *
+ * ublockexp is the log2() of number of LBAs on the LUN per UNMAP block.
+ *
+ * ublockoff is the lowest LBA on the LUN aligned to UNMAP block.
*
* atomicblock is the number of blocks that can be written atomically.
*
+ * opttxferlen is the number of blocks that can be written in one operation.
+ *
* req_lun_id is the requested LUN ID. CTL only pays attention to this
* field if the CTL_LUN_FLAG_ID_REQ flag is set. If the requested LUN ID is
* not available, the LUN addition will fail. If a particular LUN ID isn't
@@ -197,6 +203,7 @@ struct ctl_be_lun {
uint16_t ublockexp; /* passed to CTL */
uint16_t ublockoff; /* passed to CTL */
uint32_t atomicblock; /* passed to CTL */
+ uint32_t opttxferlen; /* passed to CTL */
uint32_t req_lun_id; /* passed to CTL */
uint32_t lun_id; /* returned from CTL */
uint8_t serial_num[CTL_SN_LEN]; /* passed to CTL */
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 9c3e8fd..a5e45024 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -175,6 +175,8 @@ struct ctl_be_block_lun {
uint16_t pblockoff;
uint16_t ublockexp;
uint16_t ublockoff;
+ uint32_t atomicblock;
+ uint32_t opttxferlen;
struct ctl_be_block_softc *softc;
struct devstat *disk_stats;
ctl_be_block_lun_flags flags;
@@ -1845,6 +1847,8 @@ ctl_be_block_open_file(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
"file %s size %ju < block size %u", be_lun->dev_path,
(uintmax_t)be_lun->size_bytes, be_lun->blocksize);
}
+
+ be_lun->opttxferlen = CTLBLK_MAX_IO_SIZE / be_lun->blocksize;
return (error);
}
@@ -1856,7 +1860,7 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
struct cdev *dev;
struct cdevsw *devsw;
char *value;
- int error;
+ int error, atomic, maxio;
off_t ps, pss, po, pos, us, uss, uo, uos;
params = &be_lun->params;
@@ -1870,8 +1874,16 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
if (strcmp(be_lun->backend.dev.csw->d_name, "zvol") == 0) {
be_lun->dispatch = ctl_be_block_dispatch_zvol;
be_lun->get_lba_status = ctl_be_block_gls_zvol;
- } else
+ atomic = maxio = CTLBLK_MAX_IO_SIZE;
+ } else {
be_lun->dispatch = ctl_be_block_dispatch_dev;
+ atomic = 0;
+ maxio = be_lun->backend.dev.cdev->si_iosize_max;
+ if (maxio <= 0)
+ maxio = DFLTPHYS;
+ if (maxio > CTLBLK_MAX_IO_SIZE)
+ maxio = CTLBLK_MAX_IO_SIZE;
+ }
be_lun->lun_flush = ctl_be_block_flush_dev;
be_lun->unmap = ctl_be_block_unmap_dev;
be_lun->getattr = ctl_be_block_getattr_dev;
@@ -2002,6 +2014,8 @@ ctl_be_block_open_dev(struct ctl_be_block_lun *be_lun, struct ctl_lun_req *req)
be_lun->ublockoff = (uss - uos) % uss;
}
+ be_lun->atomicblock = atomic / be_lun->blocksize;
+ be_lun->opttxferlen = maxio / be_lun->blocksize;
return (0);
}
@@ -2268,10 +2282,8 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff;
be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp;
be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff;
- if (be_lun->dispatch == ctl_be_block_dispatch_zvol &&
- be_lun->blocksize != 0)
- be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /
- be_lun->blocksize;
+ be_lun->ctl_be_lun.atomicblock = be_lun->atomicblock;
+ be_lun->ctl_be_lun.opttxferlen = be_lun->opttxferlen;
/* Tell the user the blocksize we ended up using */
params->lun_size_bytes = be_lun->size_bytes;
params->blocksize_bytes = be_lun->blocksize;
@@ -2290,32 +2302,32 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
snprintf(tmpstr, sizeof(tmpstr), "MYSERIAL%4d",
softc->num_luns);
strncpy((char *)be_lun->ctl_be_lun.serial_num, tmpstr,
- ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
+ MIN(sizeof(be_lun->ctl_be_lun.serial_num),
sizeof(tmpstr)));
/* Tell the user what we used for a serial number */
strncpy((char *)params->serial_num, tmpstr,
- ctl_min(sizeof(params->serial_num), sizeof(tmpstr)));
+ MIN(sizeof(params->serial_num), sizeof(tmpstr)));
} else {
strncpy((char *)be_lun->ctl_be_lun.serial_num,
params->serial_num,
- ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
+ MIN(sizeof(be_lun->ctl_be_lun.serial_num),
sizeof(params->serial_num)));
}
if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%4d", softc->num_luns);
strncpy((char *)be_lun->ctl_be_lun.device_id, tmpstr,
- ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
+ MIN(sizeof(be_lun->ctl_be_lun.device_id),
sizeof(tmpstr)));
/* Tell the user what we used for a device ID */
strncpy((char *)params->device_id, tmpstr,
- ctl_min(sizeof(params->device_id), sizeof(tmpstr)));
+ MIN(sizeof(params->device_id), sizeof(tmpstr)));
} else {
strncpy((char *)be_lun->ctl_be_lun.device_id,
params->device_id,
- ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
- sizeof(params->device_id)));
+ MIN(sizeof(be_lun->ctl_be_lun.device_id),
+ sizeof(params->device_id)));
}
TASK_INIT(&be_lun->io_task, /*priority*/0, ctl_be_block_worker, be_lun);
@@ -2649,10 +2661,8 @@ ctl_be_block_modify(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
be_lun->ctl_be_lun.pblockoff = be_lun->pblockoff;
be_lun->ctl_be_lun.ublockexp = be_lun->ublockexp;
be_lun->ctl_be_lun.ublockoff = be_lun->ublockoff;
- if (be_lun->dispatch == ctl_be_block_dispatch_zvol &&
- be_lun->blocksize != 0)
- be_lun->ctl_be_lun.atomicblock = CTLBLK_MAX_IO_SIZE /
- be_lun->blocksize;
+ be_lun->ctl_be_lun.atomicblock = be_lun->atomicblock;
+ be_lun->ctl_be_lun.opttxferlen = be_lun->opttxferlen;
ctl_lun_capacity_changed(&be_lun->ctl_be_lun);
if (oldsize == 0 && be_lun->size_blocks != 0)
ctl_lun_online(&be_lun->ctl_be_lun);
diff --git a/sys/cam/ctl/ctl_backend_ramdisk.c b/sys/cam/ctl/ctl_backend_ramdisk.c
index adace4f..d43cb60 100644
--- a/sys/cam/ctl/ctl_backend_ramdisk.c
+++ b/sys/cam/ctl/ctl_backend_ramdisk.c
@@ -313,8 +313,7 @@ ctl_backend_ramdisk_continue(union ctl_io *io)
sg_entries = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
for (i = 0, len_filled = 0; i < sg_filled; i++) {
sg_entries[i].addr = softc->ramdisk_pages[i];
- sg_entries[i].len = ctl_min(PAGE_SIZE,
- len - len_filled);
+ sg_entries[i].len = MIN(PAGE_SIZE, len - len_filled);
len_filled += sg_entries[i].len;
}
io->io_hdr.flags |= CTL_FLAG_KDPTR_SGLIST;
@@ -570,6 +569,8 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
be_lun->size_bytes = be_lun->size_blocks * blocksize;
be_lun->ctl_be_lun.maxlba = be_lun->size_blocks - 1;
+ be_lun->ctl_be_lun.atomicblock = UINT32_MAX;
+ be_lun->ctl_be_lun.opttxferlen = softc->rd_size / blocksize;
} else {
be_lun->ctl_be_lun.maxlba = 0;
blocksize = 0;
@@ -596,7 +597,6 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
if (unmap)
be_lun->ctl_be_lun.flags |= CTL_LUN_FLAG_UNMAP;
- be_lun->ctl_be_lun.atomicblock = UINT32_MAX;
be_lun->ctl_be_lun.be_lun = be_lun;
if (params->flags & CTL_LUN_FLAG_ID_REQ) {
@@ -613,32 +613,32 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
snprintf(tmpstr, sizeof(tmpstr), "MYSERIAL%4d",
softc->num_luns);
strncpy((char *)be_lun->ctl_be_lun.serial_num, tmpstr,
- ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
- sizeof(tmpstr)));
+ MIN(sizeof(be_lun->ctl_be_lun.serial_num),
+ sizeof(tmpstr)));
/* Tell the user what we used for a serial number */
strncpy((char *)params->serial_num, tmpstr,
- ctl_min(sizeof(params->serial_num), sizeof(tmpstr)));
+ MIN(sizeof(params->serial_num), sizeof(tmpstr)));
} else {
strncpy((char *)be_lun->ctl_be_lun.serial_num,
params->serial_num,
- ctl_min(sizeof(be_lun->ctl_be_lun.serial_num),
- sizeof(params->serial_num)));
+ MIN(sizeof(be_lun->ctl_be_lun.serial_num),
+ sizeof(params->serial_num)));
}
if ((params->flags & CTL_LUN_FLAG_DEVID) == 0) {
snprintf(tmpstr, sizeof(tmpstr), "MYDEVID%4d", softc->num_luns);
strncpy((char *)be_lun->ctl_be_lun.device_id, tmpstr,
- ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
- sizeof(tmpstr)));
+ MIN(sizeof(be_lun->ctl_be_lun.device_id),
+ sizeof(tmpstr)));
/* Tell the user what we used for a device ID */
strncpy((char *)params->device_id, tmpstr,
- ctl_min(sizeof(params->device_id), sizeof(tmpstr)));
+ MIN(sizeof(params->device_id), sizeof(tmpstr)));
} else {
strncpy((char *)be_lun->ctl_be_lun.device_id,
params->device_id,
- ctl_min(sizeof(be_lun->ctl_be_lun.device_id),
- sizeof(params->device_id)));
+ MIN(sizeof(be_lun->ctl_be_lun.device_id),
+ sizeof(params->device_id)));
}
STAILQ_INIT(&be_lun->cont_queue);
diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c
index 52dc31c..982675e 100644
--- a/sys/cam/ctl/ctl_frontend.c
+++ b/sys/cam/ctl/ctl_frontend.c
@@ -68,21 +68,22 @@ extern struct ctl_softc *control_softc;
int
ctl_frontend_register(struct ctl_frontend *fe)
{
+ struct ctl_softc *softc = control_softc;
struct ctl_frontend *fe_tmp;
- KASSERT(control_softc != NULL, ("CTL is not initialized"));
+ KASSERT(softc != NULL, ("CTL is not initialized"));
/*
* Sanity check, make sure this isn't a duplicate registration.
*/
- mtx_lock(&control_softc->ctl_lock);
- STAILQ_FOREACH(fe_tmp, &control_softc->fe_list, links) {
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_FOREACH(fe_tmp, &softc->fe_list, links) {
if (strcmp(fe_tmp->name, fe->name) == 0) {
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (-1);
}
}
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
STAILQ_INIT(&fe->port_list);
/*
@@ -91,24 +92,25 @@ ctl_frontend_register(struct ctl_frontend *fe)
if (fe->init != NULL)
fe->init();
- mtx_lock(&control_softc->ctl_lock);
- control_softc->num_frontends++;
- STAILQ_INSERT_TAIL(&control_softc->fe_list, fe, links);
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
+ softc->num_frontends++;
+ STAILQ_INSERT_TAIL(&softc->fe_list, fe, links);
+ mtx_unlock(&softc->ctl_lock);
return (0);
}
int
ctl_frontend_deregister(struct ctl_frontend *fe)
{
+ struct ctl_softc *softc = control_softc;
if (!STAILQ_EMPTY(&fe->port_list))
return (-1);
- mtx_lock(&control_softc->ctl_lock);
- STAILQ_REMOVE(&control_softc->fe_list, fe, ctl_frontend, links);
- control_softc->num_frontends--;
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_REMOVE(&softc->fe_list, fe, ctl_frontend, links);
+ softc->num_frontends--;
+ mtx_unlock(&softc->ctl_lock);
/*
* Call the frontend's shutdown routine.
@@ -121,41 +123,42 @@ ctl_frontend_deregister(struct ctl_frontend *fe)
struct ctl_frontend *
ctl_frontend_find(char *frontend_name)
{
- struct ctl_softc *ctl_softc = control_softc;
+ struct ctl_softc *softc = control_softc;
struct ctl_frontend *fe;
- mtx_lock(&ctl_softc->ctl_lock);
- STAILQ_FOREACH(fe, &ctl_softc->fe_list, links) {
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_FOREACH(fe, &softc->fe_list, links) {
if (strcmp(fe->name, frontend_name) == 0) {
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (fe);
}
}
- mtx_unlock(&ctl_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (NULL);
}
int
ctl_port_register(struct ctl_port *port)
{
+ struct ctl_softc *softc = control_softc;
void *pool;
int port_num;
int retval;
retval = 0;
- KASSERT(control_softc != NULL, ("CTL is not initialized"));
+ KASSERT(softc != NULL, ("CTL is not initialized"));
- mtx_lock(&control_softc->ctl_lock);
- port_num = ctl_ffz(control_softc->ctl_port_mask, CTL_MAX_PORTS);
+ mtx_lock(&softc->ctl_lock);
+ port_num = ctl_ffz(softc->ctl_port_mask, CTL_MAX_PORTS);
if ((port_num == -1)
- || (ctl_set_mask(control_softc->ctl_port_mask, port_num) == -1)) {
+ || (ctl_set_mask(softc->ctl_port_mask, port_num) == -1)) {
port->targ_port = -1;
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
return (1);
}
- control_softc->num_ports++;
- mtx_unlock(&control_softc->ctl_lock);
+ softc->num_ports++;
+ mtx_unlock(&softc->ctl_lock);
/*
* Initialize the initiator and portname mappings
@@ -176,15 +179,15 @@ ctl_port_register(struct ctl_port *port)
* pending sense queue on the next command, whether or not it is
* a REQUEST SENSE.
*/
- retval = ctl_pool_create(control_softc, port->port_name,
+ retval = ctl_pool_create(softc, port->port_name,
port->num_requested_ctl_io + 20, &pool);
if (retval != 0) {
free(port->wwpn_iid, M_CTL);
error:
port->targ_port = -1;
- mtx_lock(&control_softc->ctl_lock);
- ctl_clear_mask(control_softc->ctl_port_mask, port_num);
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
+ ctl_clear_mask(softc->ctl_port_mask, port_num);
+ mtx_unlock(&softc->ctl_lock);
return (retval);
}
port->ctl_pool_ref = pool;
@@ -192,12 +195,12 @@ error:
if (port->options.stqh_first == NULL)
STAILQ_INIT(&port->options);
- mtx_lock(&control_softc->ctl_lock);
- port->targ_port = port_num + control_softc->port_offset;
+ mtx_lock(&softc->ctl_lock);
+ port->targ_port = port_num + softc->port_offset;
STAILQ_INSERT_TAIL(&port->frontend->port_list, port, fe_links);
- STAILQ_INSERT_TAIL(&control_softc->port_list, port, links);
- control_softc->ctl_ports[port_num] = port;
- mtx_unlock(&control_softc->ctl_lock);
+ STAILQ_INSERT_TAIL(&softc->port_list, port, links);
+ softc->ctl_ports[port_num] = port;
+ mtx_unlock(&softc->ctl_lock);
return (retval);
}
@@ -205,6 +208,7 @@ error:
int
ctl_port_deregister(struct ctl_port *port)
{
+ struct ctl_softc *softc = control_softc;
struct ctl_io_pool *pool;
int port_num, retval, i;
@@ -217,15 +221,15 @@ ctl_port_deregister(struct ctl_port *port)
goto bailout;
}
- mtx_lock(&control_softc->ctl_lock);
- STAILQ_REMOVE(&control_softc->port_list, port, ctl_port, links);
+ mtx_lock(&softc->ctl_lock);
+ STAILQ_REMOVE(&softc->port_list, port, ctl_port, links);
STAILQ_REMOVE(&port->frontend->port_list, port, ctl_port, fe_links);
- control_softc->num_ports--;
+ softc->num_ports--;
port_num = (port->targ_port < CTL_MAX_PORTS) ? port->targ_port :
port->targ_port - CTL_MAX_PORTS;
- ctl_clear_mask(control_softc->ctl_port_mask, port_num);
- control_softc->ctl_ports[port_num] = NULL;
- mtx_unlock(&control_softc->ctl_lock);
+ ctl_clear_mask(softc->ctl_port_mask, port_num);
+ softc->ctl_ports[port_num] = NULL;
+ mtx_unlock(&softc->ctl_lock);
ctl_pool_free(pool);
ctl_free_opts(&port->options);
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index cb17aec..e779e48 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -401,8 +401,8 @@ cfcs_datamove(union ctl_io *io)
i < cam_sg_count && j < ctl_sg_count;) {
uint8_t *cam_ptr, *ctl_ptr;
- len_to_copy = ctl_min(cam_sglist[i].ds_len - cam_watermark,
- ctl_sglist[j].len - ctl_watermark);
+ len_to_copy = MIN(cam_sglist[i].ds_len - cam_watermark,
+ ctl_sglist[j].len - ctl_watermark);
cam_ptr = (uint8_t *)cam_sglist[i].ds_addr;
cam_ptr = cam_ptr + cam_watermark;
diff --git a/sys/cam/ctl/ctl_frontend_internal.c b/sys/cam/ctl/ctl_frontend_internal.c
index 7e7adda..23bd0cf 100644
--- a/sys/cam/ctl/ctl_frontend_internal.c
+++ b/sys/cam/ctl/ctl_frontend_internal.c
@@ -499,8 +499,8 @@ cfi_datamove(union ctl_io *io)
i < ext_sg_entries && j < kern_sg_entries;) {
uint8_t *ext_ptr, *kern_ptr;
- len_to_copy = ctl_min(ext_sglist[i].len - ext_watermark,
- kern_sglist[j].len - kern_watermark);
+ len_to_copy = MIN(ext_sglist[i].len - ext_watermark,
+ kern_sglist[j].len - kern_watermark);
ext_ptr = (uint8_t *)ext_sglist[i].addr;
ext_ptr = ext_ptr + ext_watermark;
@@ -1103,8 +1103,8 @@ cfi_metatask_bbr_errorparse(struct cfi_metatask *metatask, union ctl_io *io)
metatask->taskinfo.bbrread.scsi_status = io->scsiio.scsi_status;
memcpy(&metatask->taskinfo.bbrread.sense_data, &io->scsiio.sense_data,
- ctl_min(sizeof(metatask->taskinfo.bbrread.sense_data),
- sizeof(io->scsiio.sense_data)));
+ MIN(sizeof(metatask->taskinfo.bbrread.sense_data),
+ sizeof(io->scsiio.sense_data)));
if (io->scsiio.scsi_status == SCSI_STATUS_RESERV_CONFLICT) {
metatask->status = CFI_MT_ERROR;
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index 90a31ae..4e67ce1 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -145,8 +145,6 @@ struct tpc_list {
TAILQ_ENTRY(tpc_list) links;
};
-extern struct ctl_softc *control_softc;
-
static void
tpc_timeout(void *arg)
{
@@ -216,6 +214,7 @@ ctl_tpc_lun_init(struct ctl_lun *lun)
void
ctl_tpc_lun_shutdown(struct ctl_lun *lun)
{
+ struct ctl_softc *softc = lun->ctl_softc;
struct tpc_list *list;
struct tpc_token *token, *ttoken;
@@ -228,11 +227,11 @@ ctl_tpc_lun_shutdown(struct ctl_lun *lun)
}
/* Free ROD tokens for this LUN. */
- mtx_assert(&control_softc->ctl_lock, MA_OWNED);
- TAILQ_FOREACH_SAFE(token, &control_softc->tpc_tokens, links, ttoken) {
+ mtx_assert(&softc->ctl_lock, MA_OWNED);
+ TAILQ_FOREACH_SAFE(token, &softc->tpc_tokens, links, ttoken) {
if (token->lun != lun->lun || token->active)
continue;
- TAILQ_REMOVE(&control_softc->tpc_tokens, token, links);
+ TAILQ_REMOVE(&softc->tpc_tokens, token, links);
free(token->params, M_CTL);
free(token, M_CTL);
}
@@ -796,7 +795,8 @@ tpc_resolve(struct tpc_list *list, uint16_t idx, uint32_t *ss)
}
if (idx >= list->ncscd)
return (UINT64_MAX);
- return (tpcl_resolve(list->init_port, &list->cscd[idx], ss));
+ return (tpcl_resolve(list->lun->ctl_softc,
+ list->init_port, &list->cscd[idx], ss));
}
static int
@@ -1296,6 +1296,7 @@ static void
tpc_process(struct tpc_list *list)
{
struct ctl_lun *lun = list->lun;
+ struct ctl_softc *softc = lun->ctl_softc;
struct scsi_ec_segment *seg;
struct ctl_scsiio *ctsio = list->ctsio;
int retval = CTL_RETVAL_COMPLETE;
@@ -1349,10 +1350,10 @@ done:
free(list->params, M_CTL);
list->params = NULL;
if (list->token) {
- mtx_lock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
if (--list->token->active == 0)
list->token->last_active = time_uptime;
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
list->token = NULL;
}
mtx_lock(&lun->lun_lock);
@@ -1831,6 +1832,7 @@ ctl_populate_token(struct ctl_scsiio *ctsio)
{
struct scsi_populate_token *cdb;
struct scsi_populate_token_data *data;
+ struct ctl_softc *softc;
struct ctl_lun *lun;
struct ctl_port *port;
struct tpc_list *list, *tlist;
@@ -1840,7 +1842,8 @@ ctl_populate_token(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_populate_token\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- port = control_softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
+ softc = lun->ctl_softc;
+ port = softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
cdb = (struct scsi_populate_token *)ctsio->cdb;
len = scsi_4btoul(cdb->length);
@@ -1944,9 +1947,9 @@ ctl_populate_token(struct ctl_scsiio *ctsio)
list->curseg = 0;
list->completed = 1;
list->last_active = time_uptime;
- mtx_lock(&control_softc->ctl_lock);
- TAILQ_INSERT_TAIL(&control_softc->tpc_tokens, token, links);
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_lock(&softc->ctl_lock);
+ TAILQ_INSERT_TAIL(&softc->tpc_tokens, token, links);
+ mtx_unlock(&softc->ctl_lock);
ctl_set_success(ctsio);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
@@ -1965,6 +1968,7 @@ ctl_write_using_token(struct ctl_scsiio *ctsio)
{
struct scsi_write_using_token *cdb;
struct scsi_write_using_token_data *data;
+ struct ctl_softc *softc;
struct ctl_lun *lun;
struct tpc_list *list, *tlist;
struct tpc_token *token;
@@ -1973,6 +1977,7 @@ ctl_write_using_token(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_write_using_token\n"));
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ softc = lun->ctl_softc;
cdb = (struct scsi_write_using_token *)ctsio->cdb;
len = scsi_4btoul(cdb->length);
@@ -2051,8 +2056,8 @@ ctl_write_using_token(struct ctl_scsiio *ctsio)
return (CTL_RETVAL_COMPLETE);
}
- mtx_lock(&control_softc->ctl_lock);
- TAILQ_FOREACH(token, &control_softc->tpc_tokens, links) {
+ mtx_lock(&softc->ctl_lock);
+ TAILQ_FOREACH(token, &softc->tpc_tokens, links) {
if (memcmp(token->token, data->rod_token,
sizeof(data->rod_token)) == 0)
break;
@@ -2063,7 +2068,7 @@ ctl_write_using_token(struct ctl_scsiio *ctsio)
if (data->flags & EC_WUT_DEL_TKN)
token->timeout = 0;
}
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
if (token == NULL) {
mtx_lock(&lun->lun_lock);
TAILQ_REMOVE(&lun->tpc_lists, list, links);
@@ -2188,6 +2193,7 @@ ctl_receive_rod_token_information(struct ctl_scsiio *ctsio)
int
ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio)
{
+ struct ctl_softc *softc;
struct ctl_lun *lun;
struct scsi_report_all_rod_tokens *cdb;
struct scsi_report_all_rod_tokens_data *data;
@@ -2199,14 +2205,15 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio)
cdb = (struct scsi_report_all_rod_tokens *)ctsio->cdb;
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+ softc = lun->ctl_softc;
retval = CTL_RETVAL_COMPLETE;
tokens = 0;
- mtx_lock(&control_softc->ctl_lock);
- TAILQ_FOREACH(token, &control_softc->tpc_tokens, links)
+ mtx_lock(&softc->ctl_lock);
+ TAILQ_FOREACH(token, &softc->tpc_tokens, links)
tokens++;
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
if (tokens > 512)
tokens = 512;
@@ -2231,15 +2238,15 @@ ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio)
data = (struct scsi_report_all_rod_tokens_data *)ctsio->kern_data_ptr;
i = 0;
- mtx_lock(&control_softc->ctl_lock);
- TAILQ_FOREACH(token, &control_softc->tpc_tokens, links) {
+ mtx_lock(&softc->ctl_lock);
+ TAILQ_FOREACH(token, &softc->tpc_tokens, links) {
if (i >= tokens)
break;
memcpy(&data->rod_management_token_list[i * 96],
token->token, 96);
i++;
}
- mtx_unlock(&control_softc->ctl_lock);
+ mtx_unlock(&softc->ctl_lock);
scsi_ulto4b(sizeof(*data) - 4 + i * 96, data->available_data);
/*
printf("RART tokens=%d\n", i);
diff --git a/sys/cam/ctl/ctl_tpc.h b/sys/cam/ctl/ctl_tpc.h
index ecbaec1..ffdab5a 100644
--- a/sys/cam/ctl/ctl_tpc.h
+++ b/sys/cam/ctl/ctl_tpc.h
@@ -31,7 +31,8 @@
void tpc_done(union ctl_io *io);
-uint64_t tpcl_resolve(int init_port, struct scsi_ec_cscd *cscd, uint32_t *ss);
+uint64_t tpcl_resolve(struct ctl_softc *softc, int init_port,
+ struct scsi_ec_cscd *cscd, uint32_t *ss);
union ctl_io * tpcl_alloc_io(void);
int tpcl_queue(union ctl_io *io, uint64_t lun);
diff --git a/sys/cam/ctl/ctl_tpc_local.c b/sys/cam/ctl/ctl_tpc_local.c
index 97a5f98..63360fe 100644
--- a/sys/cam/ctl/ctl_tpc_local.c
+++ b/sys/cam/ctl/ctl_tpc_local.c
@@ -63,7 +63,6 @@ struct tpcl_softc {
int cur_tag_num;
};
-extern struct ctl_softc *control_softc;
static struct tpcl_softc tpcl_softc;
static int tpcl_init(void);
@@ -309,9 +308,9 @@ tpcl_done(union ctl_io *io)
}
uint64_t
-tpcl_resolve(int init_port, struct scsi_ec_cscd *cscd, uint32_t *ss)
+tpcl_resolve(struct ctl_softc *softc, int init_port,
+ struct scsi_ec_cscd *cscd, uint32_t *ss)
{
- struct ctl_softc *softc = control_softc;
struct scsi_ec_cscd_id *cscdid;
struct ctl_port *port;
struct ctl_lun *lun;
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index a1f39d2..b1dba8c 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -228,8 +228,6 @@ static struct ctl_frontend ctlfe_frontend =
};
CTL_FRONTEND_DECLARE(ctlfe, ctlfe_frontend);
-extern struct ctl_softc *control_softc;
-
void
ctlfeshutdown(void)
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
index 66552c3..665165a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
@@ -81,16 +81,14 @@ dbuf_compare(const void *x1, const void *x2)
return (1);
}
- if (d1->db_state < d2->db_state) {
+ if (d1->db_state == DB_SEARCH) {
+ ASSERT3S(d2->db_state, !=, DB_SEARCH);
return (-1);
- }
- if (d1->db_state > d2->db_state) {
+ } else if (d2->db_state == DB_SEARCH) {
+ ASSERT3S(d1->db_state, !=, DB_SEARCH);
return (1);
}
- ASSERT3S(d1->db_state, !=, DB_SEARCH);
- ASSERT3S(d2->db_state, !=, DB_SEARCH);
-
if ((uintptr_t)d1 < (uintptr_t)d2) {
return (-1);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
index 2d0cf23..c4ee741 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
@@ -536,8 +536,7 @@ spa_config_update(spa_t *spa, int what)
/*
* Update the global config cache to reflect the new mosconfig.
*/
- if (!spa->spa_is_root)
- spa_config_sync(spa, B_FALSE, what != SPA_CONFIG_UPDATE_POOL);
+ spa_config_sync(spa, B_FALSE, what != SPA_CONFIG_UPDATE_POOL);
if (what == SPA_CONFIG_UPDATE_POOL)
spa_config_update(spa, SPA_CONFIG_UPDATE_VDEVS);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h
index 52b8f30..75c6b37 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zvol.h
@@ -43,7 +43,7 @@ extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
extern int zvol_create_minor(const char *);
extern int zvol_remove_minor(const char *);
extern void zvol_remove_minors(const char *);
-extern int zvol_set_volsize(const char *, major_t, uint64_t);
+extern int zvol_set_volsize(const char *, uint64_t);
#ifdef sun
extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index d730083..383b789 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -2482,8 +2482,7 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
err = dsl_dataset_set_refreservation(dsname, source, intval);
break;
case ZFS_PROP_VOLSIZE:
- err = zvol_set_volsize(dsname, ddi_driver_major(zfs_dip),
- intval);
+ err = zvol_set_volsize(dsname, intval);
break;
case ZFS_PROP_VERSION:
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 5d7fa70..9b11652 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -6180,15 +6180,20 @@ zfs_freebsd_create(ap)
{
struct componentname *cnp = ap->a_cnp;
vattr_t *vap = ap->a_vap;
- int mode;
+ int error, mode;
ASSERT(cnp->cn_flags & SAVENAME);
vattr_init_mask(vap);
mode = vap->va_mode & ALLPERMS;
- return (zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode,
- ap->a_vpp, cnp->cn_cred, cnp->cn_thread));
+ error = zfs_create(ap->a_dvp, cnp->cn_nameptr, vap, !EXCL, mode,
+ ap->a_vpp, cnp->cn_cred, cnp->cn_thread);
+#ifdef FREEBSD_NAMECACHE
+ if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
+#endif
+ return (error);
}
static int
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
index 3925e90..afda3e4 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -704,18 +704,20 @@ zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp)
zfs_panic_recover("blkptr at %p DVA %u has invalid "
"VDEV %llu",
bp, i, (longlong_t)vdevid);
+ continue;
}
vdev_t *vd = spa->spa_root_vdev->vdev_child[vdevid];
if (vd == NULL) {
zfs_panic_recover("blkptr at %p DVA %u has invalid "
"VDEV %llu",
bp, i, (longlong_t)vdevid);
+ continue;
}
if (vd->vdev_ops == &vdev_hole_ops) {
zfs_panic_recover("blkptr at %p DVA %u has hole "
"VDEV %llu",
bp, i, (longlong_t)vdevid);
-
+ continue;
}
if (vd->vdev_ops == &vdev_missing_ops) {
/*
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
index 260822c..f9cc3eb 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -97,6 +97,7 @@
#include "zfs_namecheck.h"
+#ifndef illumos
struct g_class zfs_zvol_class = {
.name = "ZFS::ZVOL",
.version = G_VERSION,
@@ -104,25 +105,37 @@ struct g_class zfs_zvol_class = {
DECLARE_GEOM_CLASS(zfs_zvol_class, zfs_zvol);
+#endif
void *zfsdev_state;
static char *zvol_tag = "zvol_tag";
#define ZVOL_DUMPSIZE "dumpsize"
/*
- * The spa_namespace_lock protects the zfsdev_state structure from being
- * modified while it's being used, e.g. an open that comes in before a
- * create finishes. It also protects temporary opens of the dataset so that,
+ * This lock protects the zfsdev_state structure from being modified
+ * while it's being used, e.g. an open that comes in before a create
+ * finishes. It also protects temporary opens of the dataset so that,
* e.g., an open doesn't get a spurious EBUSY.
*/
+#ifdef illumos
+kmutex_t zfsdev_state_lock;
+#else
+/*
+ * In FreeBSD we've replaced the upstream zfsdev_state_lock with the
+ * spa_namespace_lock in the ZVOL code.
+ */
+#define zfsdev_state_lock spa_namespace_lock
+#endif
static uint32_t zvol_minors;
+#ifndef illumos
SYSCTL_DECL(_vfs_zfs);
SYSCTL_NODE(_vfs_zfs, OID_AUTO, vol, CTLFLAG_RW, 0, "ZFS VOLUME");
static int volmode = ZFS_VOLMODE_GEOM;
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, mode, CTLFLAG_RWTUN, &volmode, 0,
"Expose as GEOM providers (1), device files (2) or neither");
+#endif
typedef struct zvol_extent {
list_node_t ze_node;
dva_t ze_dva; /* dva associated with this extent */
@@ -133,28 +146,40 @@ typedef struct zvol_extent {
* The in-core state of each volume.
*/
typedef struct zvol_state {
+#ifndef illumos
LIST_ENTRY(zvol_state) zv_links;
+#endif
char zv_name[MAXPATHLEN]; /* pool/dd name */
uint64_t zv_volsize; /* amount of space we advertise */
uint64_t zv_volblocksize; /* volume block size */
+#ifdef illumos
+ minor_t zv_minor; /* minor number */
+#else
struct cdev *zv_dev; /* non-GEOM device */
struct g_provider *zv_provider; /* GEOM provider */
+#endif
uint8_t zv_min_bs; /* minimum addressable block shift */
uint8_t zv_flags; /* readonly, dumpified, etc. */
objset_t *zv_objset; /* objset handle */
+#ifdef illumos
+ uint32_t zv_open_count[OTYPCNT]; /* open counts */
+#endif
uint32_t zv_total_opens; /* total open count */
zilog_t *zv_zilog; /* ZIL handle */
list_t zv_extents; /* List of extents for dump */
znode_t zv_znode; /* for range locking */
dmu_buf_t *zv_dbuf; /* bonus handle */
+#ifndef illumos
int zv_state;
int zv_volmode; /* Provide GEOM or cdev */
struct bio_queue_head zv_queue;
struct mtx zv_queue_mtx; /* zv_queue mutex */
+#endif
} zvol_state_t;
+#ifndef illumos
static LIST_HEAD(, zvol_state) all_zvols;
-
+#endif
/*
* zvol specific flags
*/
@@ -172,6 +197,7 @@ int zvol_maxphys = DMU_MAX_ACCESS/2;
* Toggle unmap functionality.
*/
boolean_t zvol_unmap_enabled = B_TRUE;
+#ifndef illumos
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_enabled, CTLFLAG_RWTUN,
&zvol_unmap_enabled, 0,
"Enable UNMAP functionality");
@@ -195,28 +221,30 @@ static struct cdevsw zvol_cdevsw = {
.d_flags = D_DISK | D_TRACKCLOSE,
};
-extern int zfs_set_prop_nvlist(const char *, zprop_source_t,
- nvlist_t *, nvlist_t *);
+static void zvol_geom_run(zvol_state_t *zv);
+static void zvol_geom_destroy(zvol_state_t *zv);
+static int zvol_geom_access(struct g_provider *pp, int acr, int acw, int ace);
+static void zvol_geom_start(struct bio *bp);
+static void zvol_geom_worker(void *arg);
static void zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off,
uint64_t len, boolean_t sync);
+#endif /* !illumos */
+
+extern int zfs_set_prop_nvlist(const char *, zprop_source_t,
+ nvlist_t *, nvlist_t *);
static int zvol_remove_zv(zvol_state_t *);
static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio);
static int zvol_dumpify(zvol_state_t *zv);
static int zvol_dump_fini(zvol_state_t *zv);
static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
-static void zvol_geom_run(zvol_state_t *zv);
-static void zvol_geom_destroy(zvol_state_t *zv);
-static int zvol_geom_access(struct g_provider *pp, int acr, int acw, int ace);
-static void zvol_geom_start(struct bio *bp);
-static void zvol_geom_worker(void *arg);
-
static void
-zvol_size_changed(zvol_state_t *zv)
+zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
{
-#ifdef sun
- dev_t dev = makedevice(maj, min);
+#ifdef illumos
+ dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor);
+ zv->zv_volsize = volsize;
VERIFY(ddi_prop_update_int64(dev, zfs_dip,
"Size", volsize) == DDI_SUCCESS);
VERIFY(ddi_prop_update_int64(dev, zfs_dip,
@@ -225,7 +253,8 @@ zvol_size_changed(zvol_state_t *zv)
/* Notify specfs to invalidate the cached size */
spec_size_invalidate(dev, VBLK);
spec_size_invalidate(dev, VCHR);
-#else /* !sun */
+#else /* !illumos */
+ zv->zv_volsize = volsize;
if (zv->zv_volmode == ZFS_VOLMODE_GEOM) {
struct g_provider *pp;
@@ -236,7 +265,7 @@ zvol_size_changed(zvol_state_t *zv)
g_resize_provider(pp, zv->zv_volsize);
g_topology_unlock();
}
-#endif /* !sun */
+#endif /* illumos */
}
int
@@ -292,16 +321,26 @@ zvol_get_stats(objset_t *os, nvlist_t *nv)
static zvol_state_t *
zvol_minor_lookup(const char *name)
{
+#ifdef illumos
+ minor_t minor;
+#endif
zvol_state_t *zv;
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+#ifdef illumos
+ for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) {
+ zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
+ if (zv == NULL)
+ continue;
+#else
LIST_FOREACH(zv, &all_zvols, zv_links) {
+#endif
if (strcmp(zv->zv_name, name) == 0)
- break;
+ return (zv);
}
- return (zv);
+ return (NULL);
}
/* extent mapping arg */
@@ -517,20 +556,20 @@ zil_replay_func_t *zvol_replay_vector[TX_MAX_TYPE] = {
zvol_replay_err, /* TX_WRITE2 */
};
-#ifdef sun
+#ifdef illumos
int
zvol_name2minor(const char *name, minor_t *minor)
{
zvol_state_t *zv;
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
zv = zvol_minor_lookup(name);
if (minor && zv)
*minor = zv->zv_minor;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (zv ? 0 : -1);
}
-#endif /* sun */
+#endif /* illumos */
/*
* Create a minor node (plus a whole lot more) for the specified volume.
@@ -541,19 +580,26 @@ zvol_create_minor(const char *name)
zfs_soft_state_t *zs;
zvol_state_t *zv;
objset_t *os;
+ dmu_object_info_t doi;
+#ifdef illumos
+ minor_t minor = 0;
+ char chrbuf[30], blkbuf[30];
+#else
struct cdev *dev;
struct g_provider *pp;
struct g_geom *gp;
- dmu_object_info_t doi;
uint64_t volsize, mode;
+#endif
int error;
+#ifndef illumos
ZFS_LOG(1, "Creating ZVOL %s...", name);
+#endif
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
if (zvol_minor_lookup(name) != NULL) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(EEXIST));
}
@@ -561,20 +607,20 @@ zvol_create_minor(const char *name)
error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, FTAG, &os);
if (error) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (error);
}
-#ifdef sun
+#ifdef illumos
if ((minor = zfsdev_minor_alloc()) == 0) {
dmu_objset_disown(os, FTAG);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
if (ddi_soft_state_zalloc(zfsdev_state, minor) != DDI_SUCCESS) {
dmu_objset_disown(os, FTAG);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(EAGAIN));
}
(void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME,
@@ -586,7 +632,7 @@ zvol_create_minor(const char *name)
minor, DDI_PSEUDO, 0) == DDI_FAILURE) {
ddi_soft_state_free(zfsdev_state, minor);
dmu_objset_disown(os, FTAG);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(EAGAIN));
}
@@ -597,14 +643,14 @@ zvol_create_minor(const char *name)
ddi_remove_minor_node(zfs_dip, chrbuf);
ddi_soft_state_free(zfsdev_state, minor);
dmu_objset_disown(os, FTAG);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(EAGAIN));
}
zs = ddi_get_soft_state(zfsdev_state, minor);
zs->zss_type = ZSST_ZVOL;
zv = zs->zss_data = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP);
-#else /* !sun */
+#else /* !illumos */
zv = kmem_zalloc(sizeof(*zv), KM_SLEEP);
zv->zv_state = 0;
@@ -612,7 +658,7 @@ zvol_create_minor(const char *name)
if (error) {
kmem_free(zv, sizeof(*zv));
dmu_objset_disown(os, zvol_tag);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (error);
}
error = dsl_prop_get_integer(name,
@@ -643,7 +689,7 @@ zvol_create_minor(const char *name)
0640, "%s/%s", ZVOL_DRIVER, name) != 0) {
kmem_free(zv, sizeof(*zv));
dmu_objset_disown(os, FTAG);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
zv->zv_dev = dev;
@@ -651,10 +697,13 @@ zvol_create_minor(const char *name)
dev->si_drv2 = zv;
}
LIST_INSERT_HEAD(&all_zvols, zv, zv_links);
-#endif /* !sun */
+#endif /* illumos */
(void) strlcpy(zv->zv_name, name, MAXPATHLEN);
zv->zv_min_bs = DEV_BSHIFT;
+#ifdef illumos
+ zv->zv_minor = minor;
+#endif
zv->zv_objset = os;
if (dmu_objset_is_snapshot(os) || !spa_writeable(dmu_objset_spa(os)))
zv->zv_flags |= ZVOL_RDONLY;
@@ -679,17 +728,16 @@ zvol_create_minor(const char *name)
zvol_minors++;
- mutex_exit(&spa_namespace_lock);
-
-#ifndef sun
+ mutex_exit(&zfsdev_state_lock);
+#ifndef illumos
if (zv->zv_volmode == ZFS_VOLMODE_GEOM) {
zvol_geom_run(zv);
g_topology_unlock();
}
PICKUP_GIANT();
-#endif
ZFS_LOG(1, "ZVOL %s created.", name);
+#endif
return (0);
}
@@ -700,20 +748,24 @@ zvol_create_minor(const char *name)
static int
zvol_remove_zv(zvol_state_t *zv)
{
-#ifdef sun
+#ifdef illumos
+ char nmbuf[20];
minor_t minor = zv->zv_minor;
#endif
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
if (zv->zv_total_opens != 0)
return (SET_ERROR(EBUSY));
- ZFS_LOG(1, "ZVOL %s destroyed.", zv->zv_name);
-
-#ifdef sun
+#ifdef illumos
(void) snprintf(nmbuf, sizeof (nmbuf), "%u,raw", minor);
ddi_remove_minor_node(zfs_dip, nmbuf);
+
+ (void) snprintf(nmbuf, sizeof (nmbuf), "%u", minor);
+ ddi_remove_minor_node(zfs_dip, nmbuf);
#else
+ ZFS_LOG(1, "ZVOL %s destroyed.", zv->zv_name);
+
LIST_REMOVE(zv, zv_links);
if (zv->zv_volmode == ZFS_VOLMODE_GEOM) {
g_topology_lock();
@@ -721,13 +773,15 @@ zvol_remove_zv(zvol_state_t *zv)
g_topology_unlock();
} else if (zv->zv_volmode == ZFS_VOLMODE_DEV)
destroy_dev(zv->zv_dev);
-#endif /* sun */
+#endif
avl_destroy(&zv->zv_znode.z_range_avl);
mutex_destroy(&zv->zv_znode.z_range_lock);
- kmem_free(zv, sizeof(*zv));
-
+ kmem_free(zv, sizeof (zvol_state_t));
+#ifdef illumos
+ ddi_soft_state_free(zfsdev_state, minor);
+#endif
zvol_minors--;
return (0);
}
@@ -738,13 +792,13 @@ zvol_remove_minor(const char *name)
zvol_state_t *zv;
int rc;
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
if ((zv = zvol_minor_lookup(name)) == NULL) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
rc = zvol_remove_zv(zv);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (rc);
}
@@ -762,21 +816,22 @@ zvol_first_open(zvol_state_t *zv)
if (error)
return (error);
+ zv->zv_objset = os;
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
if (error) {
ASSERT(error == 0);
dmu_objset_disown(os, zvol_tag);
return (error);
}
- zv->zv_objset = os;
+
error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
if (error) {
dmu_objset_disown(os, zvol_tag);
return (error);
}
- zv->zv_volsize = volsize;
+
+ zvol_size_changed(zv, volsize);
zv->zv_zilog = zil_open(os, zvol_get_data);
- zvol_size_changed(zv);
VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly,
NULL) == 0);
@@ -809,7 +864,7 @@ zvol_last_close(zvol_state_t *zv)
zv->zv_objset = NULL;
}
-#ifdef sun
+#ifdef illumos
int
zvol_prealloc(zvol_state_t *zv)
{
@@ -848,7 +903,7 @@ zvol_prealloc(zvol_state_t *zv)
return (0);
}
-#endif /* sun */
+#endif /* illumos */
static int
zvol_update_volsize(objset_t *os, uint64_t volsize)
@@ -856,7 +911,7 @@ zvol_update_volsize(objset_t *os, uint64_t volsize)
dmu_tx_t *tx;
int error;
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
tx = dmu_tx_create(os);
dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
@@ -880,13 +935,34 @@ zvol_update_volsize(objset_t *os, uint64_t volsize)
void
zvol_remove_minors(const char *name)
{
+#ifdef illumos
+ zvol_state_t *zv;
+ char *namebuf;
+ minor_t minor;
+
+ namebuf = kmem_zalloc(strlen(name) + 2, KM_SLEEP);
+ (void) strncpy(namebuf, name, strlen(name));
+ (void) strcat(namebuf, "/");
+ mutex_enter(&zfsdev_state_lock);
+ for (minor = 1; minor <= ZFSDEV_MAX_MINOR; minor++) {
+
+ zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
+ if (zv == NULL)
+ continue;
+ if (strncmp(namebuf, zv->zv_name, strlen(namebuf)) == 0)
+ (void) zvol_remove_zv(zv);
+ }
+ kmem_free(namebuf, strlen(name) + 2);
+
+ mutex_exit(&zfsdev_state_lock);
+#else /* !illumos */
zvol_state_t *zv, *tzv;
size_t namelen;
namelen = strlen(name);
DROP_GIANT();
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
LIST_FOREACH_SAFE(zv, &all_zvols, zv_links, tzv) {
if (strcmp(zv->zv_name, name) == 0 ||
@@ -897,69 +973,48 @@ zvol_remove_minors(const char *name)
}
}
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
PICKUP_GIANT();
+#endif /* illumos */
}
-int
-zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
+static int
+zvol_update_live_volsize(zvol_state_t *zv, uint64_t volsize)
{
- zvol_state_t *zv = NULL;
- objset_t *os;
- int error;
- dmu_object_info_t doi;
uint64_t old_volsize = 0ULL;
- uint64_t readonly;
-
- mutex_enter(&spa_namespace_lock);
- zv = zvol_minor_lookup(name);
- if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
- mutex_exit(&spa_namespace_lock);
- return (error);
- }
+ int error = 0;
- if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
- (error = zvol_check_volsize(volsize,
- doi.doi_data_block_size)) != 0)
- goto out;
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
- VERIFY(dsl_prop_get_integer(name, "readonly", &readonly,
- NULL) == 0);
- if (readonly) {
- error = EROFS;
- goto out;
- }
-
- error = zvol_update_volsize(os, volsize);
/*
* Reinitialize the dump area to the new size. If we
* failed to resize the dump area then restore it back to
- * its original size.
+ * its original size. We must set the new volsize prior
+ * to calling dumpvp_resize() to ensure that the devices'
+ * size(9P) is not visible by the dump subsystem.
*/
- if (zv && error == 0) {
+ old_volsize = zv->zv_volsize;
+ zvol_size_changed(zv, volsize);
+
#ifdef ZVOL_DUMP
- if (zv->zv_flags & ZVOL_DUMPIFIED) {
- old_volsize = zv->zv_volsize;
- zv->zv_volsize = volsize;
- if ((error = zvol_dumpify(zv)) != 0 ||
- (error = dumpvp_resize()) != 0) {
- (void) zvol_update_volsize(os, old_volsize);
- zv->zv_volsize = old_volsize;
- error = zvol_dumpify(zv);
- }
- }
-#endif /* ZVOL_DUMP */
- if (error == 0) {
- zv->zv_volsize = volsize;
- zvol_size_changed(zv);
+ if (zv->zv_flags & ZVOL_DUMPIFIED) {
+ if ((error = zvol_dumpify(zv)) != 0 ||
+ (error = dumpvp_resize()) != 0) {
+ int dumpify_error;
+
+ (void) zvol_update_volsize(zv->zv_objset, old_volsize);
+ zvol_size_changed(zv, old_volsize);
+ dumpify_error = zvol_dumpify(zv);
+ error = dumpify_error ? dumpify_error : error;
}
}
+#endif /* ZVOL_DUMP */
-#ifdef sun
+#ifdef illumos
/*
* Generate a LUN expansion event.
*/
- if (zv && error == 0) {
+ if (error == 0) {
sysevent_id_t eid;
nvlist_t *attr;
char *physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
@@ -976,22 +1031,89 @@ zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
nvlist_free(attr);
kmem_free(physpath, MAXPATHLEN);
}
-#endif /* sun */
+#endif /* illumos */
+ return (error);
+}
-out:
- dmu_objset_rele(os, FTAG);
+int
+zvol_set_volsize(const char *name, uint64_t volsize)
+{
+ zvol_state_t *zv = NULL;
+ objset_t *os;
+ int error;
+ dmu_object_info_t doi;
+ uint64_t readonly;
+ boolean_t owned = B_FALSE;
+
+ error = dsl_prop_get_integer(name,
+ zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL);
+ if (error != 0)
+ return (error);
+ if (readonly)
+ return (SET_ERROR(EROFS));
+
+ mutex_enter(&zfsdev_state_lock);
+ zv = zvol_minor_lookup(name);
+
+ if (zv == NULL || zv->zv_objset == NULL) {
+ if ((error = dmu_objset_own(name, DMU_OST_ZVOL, B_FALSE,
+ FTAG, &os)) != 0) {
+ mutex_exit(&zfsdev_state_lock);
+ return (error);
+ }
+ owned = B_TRUE;
+ if (zv != NULL)
+ zv->zv_objset = os;
+ } else {
+ os = zv->zv_objset;
+ }
+
+ if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
+ (error = zvol_check_volsize(volsize, doi.doi_data_block_size)) != 0)
+ goto out;
- mutex_exit(&spa_namespace_lock);
+ error = zvol_update_volsize(os, volsize);
+ if (error == 0 && zv != NULL)
+ error = zvol_update_live_volsize(zv, volsize);
+out:
+ if (owned) {
+ dmu_objset_disown(os, FTAG);
+ if (zv != NULL)
+ zv->zv_objset = NULL;
+ }
+ mutex_exit(&zfsdev_state_lock);
return (error);
}
/*ARGSUSED*/
+#ifdef illumos
+int
+zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr)
+#else
static int
zvol_open(struct g_provider *pp, int flag, int count)
+#endif
{
zvol_state_t *zv;
int err = 0;
+#ifdef illumos
+
+ mutex_enter(&zfsdev_state_lock);
+
+ zv = zfsdev_get_soft_state(getminor(*devp), ZSST_ZVOL);
+ if (zv == NULL) {
+ mutex_exit(&zfsdev_state_lock);
+ return (SET_ERROR(ENXIO));
+ }
+
+ if (zv->zv_total_opens == 0)
+ err = zvol_first_open(zv);
+ if (err) {
+ mutex_exit(&zfsdev_state_lock);
+ return (err);
+ }
+#else /* !illumos */
boolean_t locked = B_FALSE;
/*
@@ -1005,15 +1127,15 @@ zvol_open(struct g_provider *pp, int flag, int count)
* recursively, but that function already has all the
* necessary protection.
*/
- if (!MUTEX_HELD(&spa_namespace_lock)) {
- mutex_enter(&spa_namespace_lock);
+ if (!MUTEX_HELD(&zfsdev_state_lock)) {
+ mutex_enter(&zfsdev_state_lock);
locked = B_TRUE;
}
zv = pp->private;
if (zv == NULL) {
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
@@ -1021,13 +1143,14 @@ zvol_open(struct g_provider *pp, int flag, int count)
err = zvol_first_open(zv);
if (err) {
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (err);
}
pp->mediasize = zv->zv_volsize;
pp->stripeoffset = 0;
pp->stripesize = zv->zv_volblocksize;
}
+#endif /* illumos */
if ((flag & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
err = SET_ERROR(EROFS);
goto out;
@@ -1046,20 +1169,46 @@ zvol_open(struct g_provider *pp, int flag, int count)
}
#endif
+#ifdef illumos
+ if (zv->zv_open_count[otyp] == 0 || otyp == OTYP_LYR) {
+ zv->zv_open_count[otyp]++;
+ zv->zv_total_opens++;
+ }
+ mutex_exit(&zfsdev_state_lock);
+#else
zv->zv_total_opens += count;
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
+#endif
return (err);
out:
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
+#ifdef illumos
+ mutex_exit(&zfsdev_state_lock);
+#else
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
+#endif
return (err);
}
/*ARGSUSED*/
+#ifdef illumos
+int
+zvol_close(dev_t dev, int flag, int otyp, cred_t *cr)
+{
+ minor_t minor = getminor(dev);
+ zvol_state_t *zv;
+ int error = 0;
+
+ mutex_enter(&zfsdev_state_lock);
+
+ zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
+ if (zv == NULL) {
+ mutex_exit(&zfsdev_state_lock);
+#else /* !illumos */
static int
zvol_close(struct g_provider *pp, int flag, int count)
{
@@ -1068,15 +1217,16 @@ zvol_close(struct g_provider *pp, int flag, int count)
boolean_t locked = B_FALSE;
/* See comment in zvol_open(). */
- if (!MUTEX_HELD(&spa_namespace_lock)) {
- mutex_enter(&spa_namespace_lock);
+ if (!MUTEX_HELD(&zfsdev_state_lock)) {
+ mutex_enter(&zfsdev_state_lock);
locked = B_TRUE;
}
zv = pp->private;
if (zv == NULL) {
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
+#endif /* illumos */
return (SET_ERROR(ENXIO));
}
@@ -1089,18 +1239,30 @@ zvol_close(struct g_provider *pp, int flag, int count)
* If the open count is zero, this is a spurious close.
* That indicates a bug in the kernel / DDI framework.
*/
+#ifdef illumos
+ ASSERT(zv->zv_open_count[otyp] != 0);
+#endif
ASSERT(zv->zv_total_opens != 0);
/*
* You may get multiple opens, but only one close.
*/
+#ifdef illumos
+ zv->zv_open_count[otyp]--;
+ zv->zv_total_opens--;
+#else
zv->zv_total_opens -= count;
+#endif
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
+#ifdef illumos
+ mutex_exit(&zfsdev_state_lock);
+#else
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
+#endif
return (error);
}
@@ -1260,7 +1422,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, offset_t off, ssize_t resid,
}
}
-#ifdef sun
+#ifdef illumos
static int
zvol_dumpio_vdev(vdev_t *vd, void *addr, uint64_t offset, uint64_t origoffset,
uint64_t size, boolean_t doread, boolean_t isdump)
@@ -1353,11 +1515,16 @@ zvol_dumpio(zvol_state_t *zv, void *addr, uint64_t offset, uint64_t size,
return (error);
}
-#endif /* sun */
+int
+zvol_strategy(buf_t *bp)
+{
+ zfs_soft_state_t *zs = NULL;
+#else /* !illumos */
void
zvol_strategy(struct bio *bp)
{
+#endif /* illumos */
zvol_state_t *zv;
uint64_t off, volsize;
size_t resid;
@@ -1365,22 +1532,53 @@ zvol_strategy(struct bio *bp)
objset_t *os;
rl_t *rl;
int error = 0;
+#ifdef illumos
+ boolean_t doread = bp->b_flags & B_READ;
+#else
boolean_t doread = 0;
+#endif
boolean_t is_dumpified;
boolean_t sync;
+#ifdef illumos
+ if (getminor(bp->b_edev) == 0) {
+ error = SET_ERROR(EINVAL);
+ } else {
+ zs = ddi_get_soft_state(zfsdev_state, getminor(bp->b_edev));
+ if (zs == NULL)
+ error = SET_ERROR(ENXIO);
+ else if (zs->zss_type != ZSST_ZVOL)
+ error = SET_ERROR(EINVAL);
+ }
+
+ if (error) {
+ bioerror(bp, error);
+ biodone(bp);
+ return (0);
+ }
+
+ zv = zs->zss_data;
+
+ if (!(bp->b_flags & B_READ) && (zv->zv_flags & ZVOL_RDONLY)) {
+ bioerror(bp, EROFS);
+ biodone(bp);
+ return (0);
+ }
+
+ off = ldbtob(bp->b_blkno);
+#else /* !illumos */
if (bp->bio_to)
zv = bp->bio_to->private;
else
zv = bp->bio_dev->si_drv2;
if (zv == NULL) {
- error = ENXIO;
+ error = SET_ERROR(ENXIO);
goto out;
}
if (bp->bio_cmd != BIO_READ && (zv->zv_flags & ZVOL_RDONLY)) {
- error = EROFS;
+ error = SET_ERROR(EROFS);
goto out;
}
@@ -1398,26 +1596,41 @@ zvol_strategy(struct bio *bp)
}
off = bp->bio_offset;
+#endif /* illumos */
volsize = zv->zv_volsize;
os = zv->zv_objset;
ASSERT(os != NULL);
+#ifdef illumos
+ bp_mapin(bp);
+ addr = bp->b_un.b_addr;
+ resid = bp->b_bcount;
+
+ if (resid > 0 && (off < 0 || off >= volsize)) {
+ bioerror(bp, EIO);
+ biodone(bp);
+ return (0);
+ }
+
+ is_dumpified = zv->zv_flags & ZVOL_DUMPIFIED;
+ sync = ((!(bp->b_flags & B_ASYNC) &&
+ !(zv->zv_flags & ZVOL_WCE)) ||
+ (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)) &&
+ !doread && !is_dumpified;
+#else /* !illumos */
addr = bp->bio_data;
resid = bp->bio_length;
if (resid > 0 && (off < 0 || off >= volsize)) {
- error = EIO;
+ error = SET_ERROR(EIO);
goto out;
}
-#ifdef illumos
- is_dumpified = zv->zv_flags & ZVOL_DUMPIFIED;
-#else
is_dumpified = B_FALSE;
-#endif
- sync = !doread && !is_dumpified &&
+ sync = !doread && !is_dumpified &&
zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS;
+#endif /* illumos */
/*
* There must be no buffer changes when doing a dmu_sync() because
@@ -1426,6 +1639,7 @@ zvol_strategy(struct bio *bp)
rl = zfs_range_lock(&zv->zv_znode, off, resid,
doread ? RL_READER : RL_WRITER);
+#ifndef illumos
if (bp->bio_cmd == BIO_DELETE) {
dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
error = dmu_tx_assign(tx, TXG_WAIT);
@@ -1440,7 +1654,7 @@ zvol_strategy(struct bio *bp)
}
goto unlock;
}
-
+#endif
while (resid != 0 && off < volsize) {
size_t size = MIN(resid, zvol_maxphys);
#ifdef illumos
@@ -1476,9 +1690,21 @@ zvol_strategy(struct bio *bp)
addr += size;
resid -= size;
}
+#ifndef illumos
unlock:
+#endif
zfs_range_unlock(rl);
+#ifdef illumos
+ if ((bp->b_resid = resid) == bp->b_bcount)
+ bioerror(bp, off > volsize ? EINVAL : error);
+
+ if (sync)
+ zil_commit(zv->zv_zilog, ZVOL_OBJ);
+ biodone(bp);
+
+ return (0);
+#else /* !illumos */
bp->bio_completed = bp->bio_length - resid;
if (bp->bio_completed < bp->bio_length && off > volsize)
error = EINVAL;
@@ -1492,9 +1718,10 @@ out:
g_io_deliver(bp, error);
else
biofinish(bp, NULL, error);
+#endif /* illumos */
}
-#ifdef sun
+#ifdef illumos
/*
* Set the buffer count to the zvol maximum transfer.
* Using our own routine instead of the default minphys()
@@ -1550,17 +1777,17 @@ int
zvol_read(dev_t dev, uio_t *uio, cred_t *cr)
{
minor_t minor = getminor(dev);
-#else
+#else /* !illumos */
int
zvol_read(struct cdev *dev, struct uio *uio, int ioflag)
{
-#endif
+#endif /* illumos */
zvol_state_t *zv;
uint64_t volsize;
rl_t *rl;
int error = 0;
-#ifdef sun
+#ifdef illumos
zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
if (zv == NULL)
return (SET_ERROR(ENXIO));
@@ -1569,6 +1796,7 @@ zvol_read(struct cdev *dev, struct uio *uio, int ioflag)
#endif
volsize = zv->zv_volsize;
+ /* uio_loffset == volsize isn't an error as its required for EOF processing. */
if (uio->uio_resid > 0 &&
(uio->uio_loffset < 0 || uio->uio_loffset > volsize))
return (SET_ERROR(EIO));
@@ -1602,24 +1830,24 @@ zvol_read(struct cdev *dev, struct uio *uio, int ioflag)
return (error);
}
-#ifdef sun
+#ifdef illumos
/*ARGSUSED*/
int
zvol_write(dev_t dev, uio_t *uio, cred_t *cr)
{
minor_t minor = getminor(dev);
-#else
+#else /* !illumos */
int
zvol_write(struct cdev *dev, struct uio *uio, int ioflag)
{
-#endif
+#endif /* illumos */
zvol_state_t *zv;
uint64_t volsize;
rl_t *rl;
int error = 0;
boolean_t sync;
-#ifdef sun
+#ifdef illumos
zv = zfsdev_get_soft_state(minor, ZSST_ZVOL);
if (zv == NULL)
return (SET_ERROR(ENXIO));
@@ -1628,6 +1856,7 @@ zvol_write(struct cdev *dev, struct uio *uio, int ioflag)
#endif
volsize = zv->zv_volsize;
+ /* uio_loffset == volsize isn't an error as its required for EOF processing. */
if (uio->uio_resid > 0 &&
(uio->uio_loffset < 0 || uio->uio_loffset > volsize))
return (SET_ERROR(EIO));
@@ -1638,9 +1867,7 @@ zvol_write(struct cdev *dev, struct uio *uio, int ioflag)
zvol_minphys, uio);
return (error);
}
-#endif
-#ifdef sun
sync = !(zv->zv_flags & ZVOL_WCE) ||
#else
sync = (ioflag & IO_SYNC) ||
@@ -1677,7 +1904,7 @@ zvol_write(struct cdev *dev, struct uio *uio, int ioflag)
return (error);
}
-#ifdef sun
+#ifdef illumos
int
zvol_getefi(void *arg, int flag, uint64_t vs, uint8_t bs)
{
@@ -1806,7 +2033,7 @@ zvol_log_write_minor(void *minor_hdl, dmu_tx_t *tx, offset_t off, ssize_t resid,
/*
* END entry points to allow external callers access to the volume.
*/
-#endif /* sun */
+#endif /* illumos */
/*
* Log a DKIOCFREE/free-long-range to the ZIL with TX_TRUNCATE.
@@ -1832,7 +2059,7 @@ zvol_log_truncate(zvol_state_t *zv, dmu_tx_t *tx, uint64_t off, uint64_t len,
zil_itx_assign(zilog, itx, tx);
}
-#ifdef sun
+#ifdef illumos
/*
* Dirtbag ioctls to support mkfs(1M) for UFS filesystems. See dkio(7I).
* Also a dirtbag dkio ioctl for unmap/free-block functionality.
@@ -1846,12 +2073,12 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
int error = 0;
rl_t *rl;
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
zv = zfsdev_get_soft_state(getminor(dev), ZSST_ZVOL);
if (zv == NULL) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (SET_ERROR(ENXIO));
}
ASSERT(zv->zv_total_opens > 0);
@@ -1869,7 +2096,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dki.dki_unit = getminor(dev);
dki.dki_maxtransfer =
1 << (SPA_OLD_MAXBLOCKSHIFT - zv->zv_min_bs);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag))
error = SET_ERROR(EFAULT);
return (error);
@@ -1883,7 +2110,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dkm.dki_lbsize = 1U << zv->zv_min_bs;
dkm.dki_capacity = zv->zv_volsize >> zv->zv_min_bs;
dkm.dki_media_type = DK_UNKNOWN;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
if (ddi_copyout(&dkm, (void *)arg, sizeof (dkm), flag))
error = SET_ERROR(EFAULT);
return (error);
@@ -1898,7 +2125,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dkmext.dki_pbsize = zv->zv_volblocksize;
dkmext.dki_capacity = zv->zv_volsize >> zv->zv_min_bs;
dkmext.dki_media_type = DK_UNKNOWN;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
if (ddi_copyout(&dkmext, (void *)arg, sizeof (dkmext), flag))
error = SET_ERROR(EFAULT);
return (error);
@@ -1909,14 +2136,14 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
uint64_t vs = zv->zv_volsize;
uint8_t bs = zv->zv_min_bs;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
error = zvol_getefi((void *)arg, flag, vs, bs);
return (error);
}
case DKIOCFLUSHWRITECACHE:
dkc = (struct dk_callback *)arg;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
zil_commit(zv->zv_zilog, ZVOL_OBJ);
if ((flag & FKIOCTL) && dkc != NULL && dkc->dkc_callback) {
(*dkc->dkc_callback)(dkc->dkc_cookie, error);
@@ -1942,10 +2169,10 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
}
if (wce) {
zv->zv_flags |= ZVOL_WCE;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
} else {
zv->zv_flags &= ~ZVOL_WCE;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
zil_commit(zv->zv_zilog, ZVOL_OBJ);
}
return (0);
@@ -1997,7 +2224,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
if (df.df_start >= zv->zv_volsize)
break; /* No need to do anything... */
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
rl = zfs_range_lock(&zv->zv_znode, df.df_start, df.df_length,
RL_WRITER);
@@ -2044,10 +2271,10 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
break;
}
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (error);
}
-#endif /* sun */
+#endif /* illumos */
int
zvol_busy(void)
@@ -2060,17 +2287,24 @@ zvol_init(void)
{
VERIFY(ddi_soft_state_init(&zfsdev_state, sizeof (zfs_soft_state_t),
1) == 0);
+#ifdef illumos
+ mutex_init(&zfsdev_state_lock, NULL, MUTEX_DEFAULT, NULL);
+#else
ZFS_LOG(1, "ZVOL Initialized.");
+#endif
}
void
zvol_fini(void)
{
+#ifdef illumos
+ mutex_destroy(&zfsdev_state_lock);
+#endif
ddi_soft_state_fini(&zfsdev_state);
ZFS_LOG(1, "ZVOL Deinitialized.");
}
-#ifdef sun
+#ifdef illumos
/*ARGSUSED*/
static int
zfs_mvdev_dump_feature_check(void *arg, dmu_tx_t *tx)
@@ -2103,7 +2337,7 @@ zvol_dump_init(zvol_state_t *zv, boolean_t resize)
uint64_t version = spa_version(spa);
enum zio_checksum checksum;
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
ASSERT(vd->vdev_ops == &vdev_root_ops);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, 0,
@@ -2355,7 +2589,7 @@ zvol_dump_fini(zvol_state_t *zv)
return (0);
}
-#endif /* sun */
+#else /* !illumos */
static void
zvol_geom_run(zvol_state_t *zv)
@@ -2670,7 +2904,7 @@ zvol_rename_minor(zvol_state_t *zv, const char *newname)
struct g_provider *pp;
struct cdev *dev;
- ASSERT(MUTEX_HELD(&spa_namespace_lock));
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
if (zv->zv_volmode == ZFS_VOLMODE_GEOM) {
g_topology_lock();
@@ -2723,8 +2957,8 @@ zvol_rename_minors(const char *oldname, const char *newname)
DROP_GIANT();
/* See comment in zvol_open(). */
- if (!MUTEX_HELD(&spa_namespace_lock)) {
- mutex_enter(&spa_namespace_lock);
+ if (!MUTEX_HELD(&zfsdev_state_lock)) {
+ mutex_enter(&zfsdev_state_lock);
locked = B_TRUE;
}
@@ -2742,7 +2976,7 @@ zvol_rename_minors(const char *oldname, const char *newname)
}
if (locked)
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
PICKUP_GIANT();
}
@@ -2752,17 +2986,17 @@ zvol_d_open(struct cdev *dev, int flags, int fmt, struct thread *td)
zvol_state_t *zv;
int err = 0;
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
zv = dev->si_drv2;
if (zv == NULL) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return(ENXIO); /* zvol_create_minor() not done yet */
}
if (zv->zv_total_opens == 0)
err = zvol_first_open(zv);
if (err) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (err);
}
if ((flags & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
@@ -2784,12 +3018,12 @@ zvol_d_open(struct cdev *dev, int flags, int fmt, struct thread *td)
#endif
zv->zv_total_opens++;
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (err);
out:
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (err);
}
@@ -2799,10 +3033,10 @@ zvol_d_close(struct cdev *dev, int flags, int fmt, struct thread *td)
zvol_state_t *zv;
int err = 0;
- mutex_enter(&spa_namespace_lock);
+ mutex_enter(&zfsdev_state_lock);
zv = dev->si_drv2;
if (zv == NULL) {
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return(ENXIO);
}
@@ -2825,7 +3059,7 @@ zvol_d_close(struct cdev *dev, int flags, int fmt, struct thread *td)
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
- mutex_exit(&spa_namespace_lock);
+ mutex_exit(&zfsdev_state_lock);
return (0);
}
@@ -2933,3 +3167,4 @@ zvol_d_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct threa
return (error);
}
+#endif /* illumos */
diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
index c123cc6..805add2 100644
--- a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
@@ -464,7 +464,7 @@ dtrace_gethrestime(void)
/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c. */
int
-dtrace_trap(struct trapframe *frame)
+dtrace_trap(struct trapframe *frame, u_int type)
{
/*
* A trap can occur while DTrace executes a probe. Before
@@ -480,7 +480,7 @@ dtrace_trap(struct trapframe *frame)
* There are only a couple of trap types that are expected.
* All the rest will be handled in the usual way.
*/
- switch (frame->tf_trapno) {
+ switch (type) {
/* General protection fault. */
case T_PROTFLT:
/* Flag an illegal operation. */
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_subr.c b/sys/cddl/dev/dtrace/i386/dtrace_subr.c
index e620a8f..4073317 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/i386/dtrace_subr.c
@@ -473,7 +473,7 @@ dtrace_gethrestime(void)
/* Function to handle DTrace traps during probes. See i386/i386/trap.c */
int
-dtrace_trap(struct trapframe *frame)
+dtrace_trap(struct trapframe *frame, u_int type)
{
/*
* A trap can occur while DTrace executes a probe. Before
@@ -489,7 +489,7 @@ dtrace_trap(struct trapframe *frame)
* There are only a couple of trap types that are expected.
* All the rest will be handled in the usual way.
*/
- switch (frame->tf_trapno) {
+ switch (type) {
/* General protection fault. */
case T_PROTFLT:
/* Flag an illegal operation. */
diff --git a/sys/cddl/dev/dtrace/mips/dtrace_subr.c b/sys/cddl/dev/dtrace/mips/dtrace_subr.c
index 5565a61..4f13b98 100644
--- a/sys/cddl/dev/dtrace/mips/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/mips/dtrace_subr.c
@@ -137,11 +137,8 @@ dtrace_gethrestime(void)
/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
int
-dtrace_trap(struct trapframe *frame)
+dtrace_trap(struct trapframe *frame, u_int type)
{
- u_int type;
-
- type = (trapframe->cause & MIPS_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT;
/*
* A trap can occur while DTrace executes a probe. Before
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
index 5411ece..a89f1d3 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
@@ -262,8 +262,9 @@ dtrace_gethrestime(void)
/* Function to handle DTrace traps during probes. See powerpc/powerpc/trap.c */
int
-dtrace_trap(struct trapframe *frame)
+dtrace_trap(struct trapframe *frame, u_int type)
{
+
/*
* A trap can occur while DTrace executes a probe. Before
* executing the probe, DTrace blocks re-scheduling and sets
@@ -278,7 +279,7 @@ dtrace_trap(struct trapframe *frame)
* There are only a couple of trap types that are expected.
* All the rest will be handled in the usual way.
*/
- switch (frame->exc) {
+ switch (type) {
/* Page fault. */
case EXC_DSI:
case EXC_DSE:
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 1436a3b..66c1dbc 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1019,7 +1019,7 @@ options DUMMYNET
# One of these is mandatory:
options FFS #Fast filesystem
-options NFSCLIENT #Network File System client
+options NFSCL #Network File System client
# The rest are optional:
options AUTOFS #Automounter filesystem
@@ -1027,7 +1027,6 @@ options CD9660 #ISO 9660 filesystem
options FDESCFS #File descriptor filesystem
options FUSE #FUSE support module
options MSDOSFS #MS DOS File System (FAT, FAT32)
-options NFSSERVER #Network File System server
options NFSLOCKD #Network Lock Manager
options NFSCL #New Network Filesystem Client
options NFSD #New Network Filesystem Server
@@ -1099,8 +1098,6 @@ options NFS_MINATTRTIMO=3 # VREG attrib cache timeout in sec
options NFS_MAXATTRTIMO=60
options NFS_MINDIRATTRTIMO=30 # VDIR attrib cache timeout in sec
options NFS_MAXDIRATTRTIMO=60
-options NFS_GATHERDELAY=10 # Default write gather delay (msec)
-options NFS_WDELAYHASHSIZ=16 # and with this
options NFS_DEBUG # Enable NFS Debugging
#
@@ -2357,19 +2354,6 @@ options SND_PCM_64
options SND_OLDSTEREO
#
-# IEEE-488 hardware:
-# pcii: PCIIA cards (uPD7210 based isa cards)
-# tnt4882: National Instruments PCI-GPIB card.
-
-device pcii
-hint.pcii.0.at="isa"
-hint.pcii.0.port="0x2e1"
-hint.pcii.0.irq="5"
-hint.pcii.0.drq="1"
-
-device tnt4882
-
-#
# Miscellaneous hardware:
#
# scd: Sony CD-ROM using proprietary (non-ATAPI) interface
@@ -2596,7 +2580,7 @@ device pcfclock
# Kernel BOOTP support
options BOOTP # Use BOOTP to obtain IP address/hostname
- # Requires NFSCLIENT and NFS_ROOT
+ # Requires NFSCL and NFS_ROOT
options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info
options BOOTP_NFSV3 # Use NFS v3 to NFS mount root
options BOOTP_COMPAT # Workaround for broken bootp daemons.
@@ -2788,7 +2772,7 @@ options U3G_DEBUG
# options for ukbd:
options UKBD_DFLT_KEYMAP # specify the built-in keymap
-makeoptions UKBD_DFLT_KEYMAP=it.iso
+makeoptions UKBD_DFLT_KEYMAP=jp.pc98
# options for uplcom:
options UPLCOM_INTR_INTERVAL=100 # interrupt pipe interval
diff --git a/sys/conf/files b/sys/conf/files
index 939b635..237390f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1448,10 +1448,6 @@ dev/ida/ida_eisa.c optional ida eisa
dev/ida/ida_pci.c optional ida pci
dev/ie/if_ie.c optional ie isa nowerror
dev/ie/if_ie_isa.c optional ie isa
-dev/ieee488/ibfoo.c optional pcii | tnt4882
-dev/ieee488/pcii.c optional pcii
-dev/ieee488/tnt4882.c optional tnt4882
-dev/ieee488/upd7210.c optional pcii | tnt4882
dev/iicbus/ad7418.c optional ad7418
dev/iicbus/ds133x.c optional ds133x
dev/iicbus/ds1374.c optional ds1374
@@ -3559,24 +3555,12 @@ 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 nfsclient | bootp nfscl
-nfs/krpc_subr.c optional bootp nfsclient | bootp nfscl
-nfs/nfs_common.c optional nfsclient | nfsserver
-nfs/nfs_diskless.c optional nfsclient nfs_root | nfscl nfs_root
-nfs/nfs_fha.c optional nfsserver | nfsd
-nfs/nfs_lock.c optional nfsclient | nfscl | nfslockd | nfsd
-nfsclient/nfs_bio.c optional nfsclient
-nfsclient/nfs_node.c optional nfsclient
-nfsclient/nfs_krpc.c optional nfsclient
-nfsclient/nfs_subs.c optional nfsclient
-nfsclient/nfs_nfsiod.c optional nfsclient
-nfsclient/nfs_vfsops.c optional nfsclient
-nfsclient/nfs_vnops.c optional nfsclient
-nfsserver/nfs_fha_old.c optional nfsserver
-nfsserver/nfs_serv.c optional nfsserver
-nfsserver/nfs_srvkrpc.c optional nfsserver
-nfsserver/nfs_srvsubs.c optional nfsserver
-nfs/nfs_nfssvc.c optional nfsserver | nfscl | nfsd
+nfs/bootp_subr.c optional bootp nfscl
+nfs/krpc_subr.c optional bootp nfscl
+nfs/nfs_diskless.c optional nfscl nfs_root
+nfs/nfs_fha.c optional nfsd
+nfs/nfs_lock.c optional nfscl | nfslockd | nfsd
+nfs/nfs_nfssvc.c optional nfscl | nfsd
nlm/nlm_advlock.c optional nfslockd | nfsd
nlm/nlm_prot_clnt.c optional nfslockd | nfsd
nlm/nlm_prot_impl.c optional nfslockd | nfsd
@@ -3887,26 +3871,26 @@ opencrypto/gfmult.c optional crypto
opencrypto/rmd160.c optional crypto | ipsec
opencrypto/skipjack.c optional crypto
opencrypto/xform.c optional crypto
-rpc/auth_none.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/auth_unix.c optional krpc | nfslockd | nfsclient | nfscl | nfsd
-rpc/authunix_prot.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/clnt_bck.c optional krpc | nfslockd | nfsserver | nfscl | nfsd
-rpc/clnt_dg.c optional krpc | nfslockd | nfsclient | nfscl | nfsd
-rpc/clnt_rc.c optional krpc | nfslockd | nfsclient | nfscl | nfsd
-rpc/clnt_vc.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/getnetconfig.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/replay.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/rpc_callmsg.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/rpc_generic.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/rpc_prot.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/rpcb_clnt.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/rpcb_prot.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/svc.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/svc_auth.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/svc_auth_unix.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-rpc/svc_dg.c optional krpc | nfslockd | nfsserver | nfscl | nfsd
-rpc/svc_generic.c optional krpc | nfslockd | nfsserver | nfscl | nfsd
-rpc/svc_vc.c optional krpc | nfslockd | nfsserver | nfscl | nfsd
+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
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
@@ -4012,9 +3996,9 @@ xen/xenbus/xenbusb_if.m optional xen | xenhvm
xen/xenbus/xenbusb.c optional xen | xenhvm
xen/xenbus/xenbusb_front.c optional xen | xenhvm
xen/xenbus/xenbusb_back.c optional xen | xenhvm
-xdr/xdr.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-xdr/xdr_array.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-xdr/xdr_mbuf.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-xdr/xdr_mem.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-xdr/xdr_reference.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
-xdr/xdr_sizeof.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
+xdr/xdr.c optional krpc | nfslockd | nfscl | nfsd
+xdr/xdr_array.c optional krpc | nfslockd | nfscl | nfsd
+xdr/xdr_mbuf.c optional krpc | nfslockd | nfscl | nfsd
+xdr/xdr_mem.c optional krpc | nfslockd | nfscl | nfsd
+xdr/xdr_reference.c optional krpc | nfslockd | nfscl | nfsd
+xdr/xdr_sizeof.c optional krpc | nfslockd | nfscl | nfsd
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 9b3b84b..c06eeaf 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -52,7 +52,11 @@ else
fi
b=share/examples/etc/bsd-style-copyright
-year=$(sed -Ee '/^Copyright .* The FreeBSD Project/!d;s/^.*1992-([0-9]*) .*$/\1/g' ${SYSDIR}/../COPYRIGHT)
+if [ -r "${SYSDIR}/../COPYRIGHT" ]; then
+ year=$(sed -Ee '/^Copyright .* The FreeBSD Project/!d;s/^.*1992-([0-9]*) .*$/\1/g' ${SYSDIR}/../COPYRIGHT)
+else
+ year=$(date +%Y)
+fi
# look for copyright template
for bsd_copyright in ../$b ../../$b ../../../$b /usr/src/$b /usr/$b
do
diff --git a/sys/conf/options b/sys/conf/options
index ae0f852..52c44a1 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -253,11 +253,6 @@ KGSSAPI_DEBUG opt_kgssapi.h
# sys/i386/i386/autoconf.c. If any of these filesystems are
# statically compiled into the kernel, code for mounting them as root
# filesystems will be enabled - but look below.
-NFSCLIENT opt_nfs.h
-NFSSERVER opt_nfs.h
-
-# Use these options to compile the experimental nfs client and/or
-# server that supports NFSv4 into a kernel.
# NFSCL - client
# NFSD - server
NFSCL opt_nfs.h
@@ -624,8 +619,6 @@ NFS_MINATTRTIMO opt_nfs.h
NFS_MAXATTRTIMO opt_nfs.h
NFS_MINDIRATTRTIMO opt_nfs.h
NFS_MAXDIRATTRTIMO opt_nfs.h
-NFS_GATHERDELAY opt_nfs.h
-NFS_WDELAYHASHSIZ opt_nfs.h
NFS_DEBUG opt_nfs.h
# For the Bt848/Bt848A/Bt849/Bt878/Bt879 driver
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 583983b..31aab5d 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -142,7 +142,7 @@ ahci_ctlr_reset(device_t dev)
}
if (timeout == 0) {
device_printf(dev, "AHCI controller reset failure\n");
- return ENXIO;
+ return (ENXIO);
}
/* Reenable AHCI mode */
ATA_OUTL(ctlr->r_mem, AHCI_GHC, AHCI_GHC_AE);
@@ -225,18 +225,18 @@ ahci_attach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
ctlr->r_mem);
rman_fini(&ctlr->sc_iomem);
- return ENXIO;
+ return (ENXIO);
}
ahci_ctlr_setup(dev);
/* Setup interrupts. */
- if (ahci_setup_interrupt(dev)) {
+ if ((error = ahci_setup_interrupt(dev)) != 0) {
bus_dma_tag_destroy(ctlr->dma_tag);
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
ctlr->r_mem);
rman_fini(&ctlr->sc_iomem);
- return ENXIO;
+ return (error);
}
i = 0;
@@ -315,7 +315,7 @@ ahci_attach(device_t dev)
device_set_ivars(child, (void *)(intptr_t)-1);
}
bus_generic_attach(dev);
- return 0;
+ return (0);
}
int
@@ -356,6 +356,14 @@ ahci_setup_interrupt(device_t dev)
device_printf(dev, "Falling back to one MSI\n");
ctlr->numirqs = 1;
}
+
+ /* Ensure we don't overrun irqs. */
+ if (ctlr->numirqs > AHCI_MAX_IRQS) {
+ device_printf(dev, "Too many irqs %d > %d (clamping)\n",
+ ctlr->numirqs, AHCI_MAX_IRQS);
+ ctlr->numirqs = AHCI_MAX_IRQS;
+ }
+
/* Allocate all IRQs. */
for (i = 0; i < ctlr->numirqs; i++) {
ctlr->irqs[i].ctlr = ctlr;
@@ -372,7 +380,7 @@ ahci_setup_interrupt(device_t dev)
if (!(ctlr->irqs[i].r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&ctlr->irqs[i].r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
device_printf(dev, "unable to map interrupt\n");
- return ENXIO;
+ return (ENXIO);
}
if ((bus_setup_intr(dev, ctlr->irqs[i].r_irq, ATA_INTR_FLAGS, NULL,
(ctlr->irqs[i].mode != AHCI_IRQ_MODE_ONE) ? ahci_intr :
@@ -381,7 +389,7 @@ ahci_setup_interrupt(device_t dev)
&ctlr->irqs[i], &ctlr->irqs[i].handle))) {
/* SOS XXX release r_irq */
device_printf(dev, "unable to setup interrupt\n");
- return ENXIO;
+ return (ENXIO);
}
if (ctlr->numirqs > 1) {
bus_describe_intr(dev, ctlr->irqs[i].r_irq,
@@ -529,7 +537,7 @@ ahci_release_resource(device_t dev, device_t child, int type, int rid,
return (0);
case SYS_RES_IRQ:
if (rid != ATA_IRQ_RID)
- return ENOENT;
+ return (ENOENT);
return (0);
}
return (EINVAL);
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index f5a3ca8..462f204 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -143,6 +143,7 @@
#define AHCI_MAX_PORTS 32
#define AHCI_MAX_SLOTS 32
+#define AHCI_MAX_IRQS 16
/* SATA AHCI v1.0 register defines */
#define AHCI_CAP 0x00
@@ -494,7 +495,7 @@ struct ahci_controller {
#define AHCI_IRQ_MODE_ALL 0
#define AHCI_IRQ_MODE_AFTER 1
#define AHCI_IRQ_MODE_ONE 2
- } irqs[16];
+ } irqs[AHCI_MAX_IRQS];
uint32_t caps; /* Controller capabilities */
uint32_t caps2; /* Controller capabilities */
uint32_t capsem; /* Controller capabilities */
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index 40a34d4..45c8ae4 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -446,7 +446,15 @@ ath_sysctl_rfsilent(SYSCTL_HANDLER_ARGS)
return error;
if (!ath_hal_setrfsilent(sc->sc_ah, rfsilent))
return EINVAL;
- sc->sc_rfsilentpin = rfsilent & 0x1c;
+ /*
+ * Earlier chips (< AR5212) have up to 8 GPIO
+ * pins exposed.
+ *
+ * AR5416 and later chips have many more GPIO
+ * pins (up to 16) so the mask is expanded to
+ * four bits.
+ */
+ sc->sc_rfsilentpin = rfsilent & 0x3c;
sc->sc_rfsilentpol = (rfsilent & 0x2) != 0;
return 0;
}
diff --git a/sys/dev/beri/virtio/virtio.c b/sys/dev/beri/virtio/virtio.c
index 4cc25c2..cb7c293 100644
--- a/sys/dev/beri/virtio/virtio.c
+++ b/sys/dev/beri/virtio/virtio.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
+#include <sys/cdefs.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
@@ -156,7 +157,7 @@ vq_getchain(uint32_t offs, struct vqueue_info *vq,
break;
next = be16toh(vp->next);
}
- paddr_unmap((void *)vindir, be32toh(vdir->len));
+ paddr_unmap(__DEVOLATILE(void *, vindir), be32toh(vdir->len));
}
if ((be16toh(vdir->flags) & VRING_DESC_F_NEXT) == 0)
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 838be4f..58f529d 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -1946,11 +1946,9 @@ bge_chipinit(struct bge_softc *sc)
/*
* Disable memory write invalidate. Apparently it is not supported
- * properly by these devices. Also ensure that INTx isn't disabled,
- * as these chips need it even when using MSI.
+ * properly by these devices.
*/
- PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD,
- PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4);
+ PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD, PCIM_CMD_MWIEN, 4);
/* Set the timer prescaler (always 66 MHz). */
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c
index 96ceb0d..ec41a2e 100644
--- a/sys/dev/cpuctl/cpuctl.c
+++ b/sys/dev/cpuctl/cpuctl.c
@@ -63,7 +63,7 @@ static d_ioctl_t cpuctl_ioctl;
# define DPRINTF(...)
#endif
-#define UCODE_SIZE_MAX (16 * 1024)
+#define UCODE_SIZE_MAX (32 * 1024)
static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd,
struct thread *td);
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index d99fdf2..f00519e 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -75,6 +75,12 @@ fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base,
u_long bus_addr, par_bus_addr, pbase, psize;
int err, i, len, tuple_size, tuples;
+ if (node == 0) {
+ *base = 0;
+ *size = ULONG_MAX;
+ return (0);
+ }
+
if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
return (ENXIO);
/*
@@ -91,9 +97,8 @@ fdt_get_range_by_busaddr(phandle_t node, u_long addr, u_long *base,
if (len > sizeof(ranges))
return (ENOMEM);
if (len == 0) {
- *base = 0;
- *size = ULONG_MAX;
- return (0);
+ return (fdt_get_range_by_busaddr(OF_parent(node), addr,
+ base, size));
}
if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 947f057..cf0e6a2 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -157,52 +157,52 @@ static const u_char fxp_cb_config_template[] = {
* them.
*/
static const struct fxp_ident fxp_ident_table[] = {
- { 0x1029, -1, 0, "Intel 82559 PCI/CardBus Pro/100" },
- { 0x1030, -1, 0, "Intel 82559 Pro/100 Ethernet" },
- { 0x1031, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
- { 0x1032, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
- { 0x1033, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
- { 0x1034, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
- { 0x1035, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
- { 0x1036, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
- { 0x1037, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
- { 0x1038, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
- { 0x1039, -1, 4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
- { 0x103A, -1, 4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
- { 0x103B, -1, 4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
- { 0x103C, -1, 4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
- { 0x103D, -1, 4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
- { 0x103E, -1, 4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
- { 0x1050, -1, 5, "Intel 82801BA (D865) Pro/100 VE Ethernet" },
- { 0x1051, -1, 5, "Intel 82562ET (ICH5/ICH5R) Pro/100 VE Ethernet" },
- { 0x1059, -1, 0, "Intel 82551QM Pro/100 M Mobile Connection" },
- { 0x1064, -1, 6, "Intel 82562EZ (ICH6)" },
- { 0x1065, -1, 6, "Intel 82562ET/EZ/GT/GZ PRO/100 VE Ethernet" },
- { 0x1068, -1, 6, "Intel 82801FBM (ICH6-M) Pro/100 VE Ethernet" },
- { 0x1069, -1, 6, "Intel 82562EM/EX/GX Pro/100 Ethernet" },
- { 0x1091, -1, 7, "Intel 82562GX Pro/100 Ethernet" },
- { 0x1092, -1, 7, "Intel Pro/100 VE Network Connection" },
- { 0x1093, -1, 7, "Intel Pro/100 VM Network Connection" },
- { 0x1094, -1, 7, "Intel Pro/100 946GZ (ICH7) Network Connection" },
- { 0x1209, -1, 0, "Intel 82559ER Embedded 10/100 Ethernet" },
- { 0x1229, 0x01, 0, "Intel 82557 Pro/100 Ethernet" },
- { 0x1229, 0x02, 0, "Intel 82557 Pro/100 Ethernet" },
- { 0x1229, 0x03, 0, "Intel 82557 Pro/100 Ethernet" },
- { 0x1229, 0x04, 0, "Intel 82558 Pro/100 Ethernet" },
- { 0x1229, 0x05, 0, "Intel 82558 Pro/100 Ethernet" },
- { 0x1229, 0x06, 0, "Intel 82559 Pro/100 Ethernet" },
- { 0x1229, 0x07, 0, "Intel 82559 Pro/100 Ethernet" },
- { 0x1229, 0x08, 0, "Intel 82559 Pro/100 Ethernet" },
- { 0x1229, 0x09, 0, "Intel 82559ER Pro/100 Ethernet" },
- { 0x1229, 0x0c, 0, "Intel 82550 Pro/100 Ethernet" },
- { 0x1229, 0x0d, 0, "Intel 82550C Pro/100 Ethernet" },
- { 0x1229, 0x0e, 0, "Intel 82550 Pro/100 Ethernet" },
- { 0x1229, 0x0f, 0, "Intel 82551 Pro/100 Ethernet" },
- { 0x1229, 0x10, 0, "Intel 82551 Pro/100 Ethernet" },
- { 0x1229, -1, 0, "Intel 82557/8/9 Pro/100 Ethernet" },
- { 0x2449, -1, 2, "Intel 82801BA/CAM (ICH2/3) Pro/100 Ethernet" },
- { 0x27dc, -1, 7, "Intel 82801GB (ICH7) 10/100 Ethernet" },
- { 0, -1, 0, NULL },
+ { 0x8086, 0x1029, -1, 0, "Intel 82559 PCI/CardBus Pro/100" },
+ { 0x8086, 0x1030, -1, 0, "Intel 82559 Pro/100 Ethernet" },
+ { 0x8086, 0x1031, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
+ { 0x8086, 0x1032, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
+ { 0x8086, 0x1033, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+ { 0x8086, 0x1034, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+ { 0x8086, 0x1035, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+ { 0x8086, 0x1036, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+ { 0x8086, 0x1037, -1, 3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+ { 0x8086, 0x1038, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+ { 0x8086, 0x1039, -1, 4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
+ { 0x8086, 0x103A, -1, 4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
+ { 0x8086, 0x103B, -1, 4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
+ { 0x8086, 0x103C, -1, 4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
+ { 0x8086, 0x103D, -1, 4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
+ { 0x8086, 0x103E, -1, 4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
+ { 0x8086, 0x1050, -1, 5, "Intel 82801BA (D865) Pro/100 VE Ethernet" },
+ { 0x8086, 0x1051, -1, 5, "Intel 82562ET (ICH5/ICH5R) Pro/100 VE Ethernet" },
+ { 0x8086, 0x1059, -1, 0, "Intel 82551QM Pro/100 M Mobile Connection" },
+ { 0x8086, 0x1064, -1, 6, "Intel 82562EZ (ICH6)" },
+ { 0x8086, 0x1065, -1, 6, "Intel 82562ET/EZ/GT/GZ PRO/100 VE Ethernet" },
+ { 0x8086, 0x1068, -1, 6, "Intel 82801FBM (ICH6-M) Pro/100 VE Ethernet" },
+ { 0x8086, 0x1069, -1, 6, "Intel 82562EM/EX/GX Pro/100 Ethernet" },
+ { 0x8086, 0x1091, -1, 7, "Intel 82562GX Pro/100 Ethernet" },
+ { 0x8086, 0x1092, -1, 7, "Intel Pro/100 VE Network Connection" },
+ { 0x8086, 0x1093, -1, 7, "Intel Pro/100 VM Network Connection" },
+ { 0x8086, 0x1094, -1, 7, "Intel Pro/100 946GZ (ICH7) Network Connection" },
+ { 0x8086, 0x1209, -1, 0, "Intel 82559ER Embedded 10/100 Ethernet" },
+ { 0x8086, 0x1229, 0x01, 0, "Intel 82557 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x02, 0, "Intel 82557 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x03, 0, "Intel 82557 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x04, 0, "Intel 82558 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x05, 0, "Intel 82558 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x06, 0, "Intel 82559 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x07, 0, "Intel 82559 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x08, 0, "Intel 82559 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x09, 0, "Intel 82559ER Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x0c, 0, "Intel 82550 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x0d, 0, "Intel 82550C Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x0e, 0, "Intel 82550 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x0f, 0, "Intel 82551 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, 0x10, 0, "Intel 82551 Pro/100 Ethernet" },
+ { 0x8086, 0x1229, -1, 0, "Intel 82557/8/9 Pro/100 Ethernet" },
+ { 0x8086, 0x2449, -1, 2, "Intel 82801BA/CAM (ICH2/3) Pro/100 Ethernet" },
+ { 0x8086, 0x27dc, -1, 7, "Intel 82801GB (ICH7) 10/100 Ethernet" },
+ { 0, 0, -1, 0, NULL },
};
#ifdef FXP_IP_CSUM_WAR
@@ -374,18 +374,18 @@ fxp_dma_wait(struct fxp_softc *sc, volatile uint16_t *status,
static const struct fxp_ident *
fxp_find_ident(device_t dev)
{
- uint16_t devid;
+ uint16_t vendor;
+ uint16_t device;
uint8_t revid;
const struct fxp_ident *ident;
- if (pci_get_vendor(dev) == FXP_VENDORID_INTEL) {
- devid = pci_get_device(dev);
- revid = pci_get_revid(dev);
- for (ident = fxp_ident_table; ident->name != NULL; ident++) {
- if (ident->devid == devid &&
- (ident->revid == revid || ident->revid == -1)) {
- return (ident);
- }
+ vendor = pci_get_vendor(dev);
+ device = pci_get_device(dev);
+ revid = pci_get_revid(dev);
+ for (ident = fxp_ident_table; ident->name != NULL; ident++) {
+ if (ident->vendor == vendor && ident->device == device &&
+ (ident->revid == revid || ident->revid == -1)) {
+ return (ident);
}
}
return (NULL);
@@ -628,7 +628,7 @@ fxp_attach(device_t dev)
/* For 82559 or later chips, Rx checksum offload is supported. */
if (sc->revision >= FXP_REV_82559_A0) {
/* 82559ER does not support Rx checksum offloading. */
- if (sc->ident->devid != 0x1209)
+ if (sc->ident->device != 0x1209)
sc->flags |= FXP_FLAG_82559_RXCSUM;
}
/*
diff --git a/sys/dev/fxp/if_fxpreg.h b/sys/dev/fxp/if_fxpreg.h
index 7fd60af..7ee8588 100644
--- a/sys/dev/fxp/if_fxpreg.h
+++ b/sys/dev/fxp/if_fxpreg.h
@@ -28,8 +28,6 @@
* $FreeBSD$
*/
-#define FXP_VENDORID_INTEL 0x8086
-
#define FXP_PCI_MMBA 0x10
#define FXP_PCI_IOBA 0x14
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index e0097a1..78200ce 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -143,7 +143,8 @@ struct fxp_desc_list {
};
struct fxp_ident {
- uint16_t devid;
+ uint16_t vendor;
+ uint16_t device;
int16_t revid; /* -1 matches anything */
uint8_t ich;
const char *name;
diff --git a/sys/dev/gpio/gpio_if.m b/sys/dev/gpio/gpio_if.m
index f0ead65..adc119e 100644
--- a/sys/dev/gpio/gpio_if.m
+++ b/sys/dev/gpio/gpio_if.m
@@ -56,11 +56,11 @@ HEADER {
};
#
-# Get total number of pins
+# Get maximum pin number
#
METHOD int pin_max {
device_t dev;
- int *npins;
+ int *maxpin;
};
#
diff --git a/sys/dev/ieee488/ibfoo.c b/sys/dev/ieee488/ibfoo.c
deleted file mode 100644
index 2fe72dc..0000000
--- a/sys/dev/ieee488/ibfoo.c
+++ /dev/null
@@ -1,1127 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
- * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
- * 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.
- *
- * High-level driver for µPD7210 based GPIB cards.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-# define IBDEBUG
-# undef IBDEBUG
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/limits.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/bus.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <isa/isavar.h>
-
-#include <dev/ieee488/ugpib.h>
-
-#define UPD7210_SW_DRIVER
-#include <dev/ieee488/upd7210.h>
-#include <dev/ieee488/tnt4882.h>
-
-static MALLOC_DEFINE(M_IBFOO, "IBFOO", "IBFOO");
-
-
-/* ibfoo API */
-
-#include <dev/ieee488/ibfoo_int.h>
-
-/* XXX: This is really a bitmap */
-enum h_kind {
- H_DEV = 1,
- H_BOARD = 2,
- H_EITHER = 3
-};
-
-struct handle {
- LIST_ENTRY(handle) list;
- int handle;
- enum h_kind kind;
- int pad;
- int sad;
- struct timeval timeout;
- int eot;
- int eos;
- int dma;
-};
-
-struct ibfoo {
- struct upd7210 *u;
- LIST_HEAD(,handle) handles;
- struct unrhdr *unrhdr;
- struct callout callout;
- struct handle *h;
- struct ibarg *ap;
-
- enum {
- IDLE,
- BUSY,
- PIO_IDATA,
- PIO_ODATA,
- PIO_CMD,
- DMA_IDATA,
- FIFO_IDATA,
- FIFO_ODATA,
- FIFO_CMD
- } mode;
-
- struct timeval deadline;
-
- struct handle *rdh; /* addressed for read */
- struct handle *wrh; /* addressed for write */
-
- int doeoi;
-
- u_char *buf;
- u_int buflen;
-};
-
-typedef int ibhandler_t(struct ibfoo *ib);
-
-static struct timeval timeouts[] = {
- [TNONE] = { 0, 0},
- [T10us] = { 0, 10},
- [T30us] = { 0, 30},
- [T100us] = { 0, 100},
- [T300us] = { 0, 300},
- [T1ms] = { 0, 1000},
- [T3ms] = { 0, 3000},
- [T10ms] = { 0, 10000},
- [T30ms] = { 0, 30000},
- [T100ms] = { 0, 100000},
- [T300ms] = { 0, 300000},
- [T1s] = { 1, 0},
- [T3s] = { 3, 0},
- [T10s] = { 10, 0},
- [T30s] = { 30, 0},
- [T100s] = { 100, 0},
- [T300s] = { 300, 0},
- [T1000s] = { 1000, 0}
-};
-
-static const u_int max_timeouts = sizeof timeouts / sizeof timeouts[0];
-
-static int ibdebug;
-
-static int
-ib_set_error(struct ibarg *ap, int error)
-{
-
- if (ap->__iberr == 0)
- ap->__iberr = error;
- ap->__ibsta |= ERR;
- ap->__retval = ap->__ibsta;
- return (0);
-}
-
-static int
-ib_had_timeout(struct ibarg *ap)
-{
-
- ib_set_error(ap, EABO);
- ap->__ibsta |= TIMO;
- ap->__retval = ap->__ibsta;
- return (0);
-}
-
-static int
-ib_set_errno(struct ibarg *ap, int errno)
-{
-
- if (ap->__iberr == 0) {
- ap->__iberr = EDVR;
- ap->__ibcnt = errno;
- }
- ap->__ibsta |= ERR;
- ap->__retval = ap->__ibsta;
- return (0);
-}
-
-static int
-gpib_ib_irq(struct upd7210 *u, int isr_3)
-{
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- mtx_assert(&u->mutex, MA_OWNED);
- switch (ib->mode) {
- case PIO_CMD:
- if (!(u->rreg[ISR2] & IXR2_CO))
- return (0);
- if (ib->buflen == 0)
- break;
- upd7210_wr(u, CDOR, *ib->buf);
- ib->buf++;
- ib->buflen--;
- return (1);
- case PIO_IDATA:
- if (!(u->rreg[ISR1] & IXR1_DI))
- return (0);
- *ib->buf = upd7210_rd(u, DIR);
- ib->buf++;
- ib->buflen--;
- if (ib->buflen == 0 || (u->rreg[ISR1] & IXR1_ENDRX))
- break;
- return (1);
- case PIO_ODATA:
- if (!(u->rreg[ISR1] & IXR1_DO))
- return (0);
- if (ib->buflen == 0)
- break;
- if (ib->buflen == 1 && ib->doeoi)
- upd7210_wr(u, AUXMR, AUXMR_SEOI);
- upd7210_wr(u, CDOR, *ib->buf);
- ib->buf++;
- ib->buflen--;
- return (1);
- case DMA_IDATA:
- if (!(u->rreg[ISR1] & IXR1_ENDRX))
- return (0);
- break;
- case FIFO_IDATA:
- if (!(isr_3 & 0x15))
- return (0);
- while (ib->buflen != 0 && (isr_3 & 0x04 /* NEF */) != 0) {
- *ib->buf = bus_read_1(u->reg_res[0], fifob);
- ib->buf++;
- ib->buflen--;
- isr_3 = bus_read_1(u->reg_res[0], isr3);
- }
- if ((isr_3 & 0x01) != 0 /* xfr done */ ||
- (u->rreg[ISR1] & IXR1_ENDRX) != 0 ||
- ib->buflen == 0)
- break;
- if (isr_3 & 0x10)
- /* xfr stopped */
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- upd7210_wr(u, AUXMR, AUXMR_RFD);
- return (1);
- case FIFO_CMD:
- case FIFO_ODATA:
- if (!(isr_3 & 0x19))
- return (0);
- if (ib->buflen == 0)
- /* xfr DONE */
- break;
- while (ib->buflen != 0 && (isr_3 & 0x08 /* NFF */) != 0) {
- bus_write_1(u->reg_res[0], fifob, *ib->buf);
- ib->buf++;
- ib->buflen--;
- isr_3 = bus_read_1(u->reg_res[0], isr3);
- }
- if (isr_3 & 0x10)
- /* xfr stopped */
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- if (ib->buflen == 0)
- /* no more NFF interrupts wanted */
- bus_write_1(u->reg_res[0], imr3, 0x11); /* STOP IE, DONE IE */
- return (1);
- default:
- return (0);
- }
- upd7210_wr(u, IMR1, 0);
- upd7210_wr(u, IMR2, 0);
- if (u->use_fifo) {
- bus_write_1(u->reg_res[0], imr3, 0x00);
- bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
- }
- ib->mode = BUSY;
- wakeup(&ib->buflen);
- return (1);
-}
-
-static void
-gpib_ib_timeout(void *arg)
-{
- struct upd7210 *u;
- struct ibfoo *ib;
- struct timeval tv;
- u_int isr_3;
-
- u = arg;
- ib = u->ibfoo;
- mtx_lock(&u->mutex);
- if (ib->mode == DMA_IDATA && isa_dmatc(u->dmachan)) {
- KASSERT(u->dmachan >= 0, ("Bogus dmachan = %d", u->dmachan));
- upd7210_wr(u, IMR1, 0);
- upd7210_wr(u, IMR2, 0);
- ib->mode = BUSY;
- wakeup(&ib->buflen);
- }
- if (ib->mode > BUSY) {
- upd7210_rd(u, ISR1);
- upd7210_rd(u, ISR2);
- if (u->use_fifo)
- isr_3 = bus_read_1(u->reg_res[0], isr3);
- else
- isr_3 = 0;
- gpib_ib_irq(u, isr_3);
- }
- if (ib->mode != IDLE && timevalisset(&ib->deadline)) {
- getmicrouptime(&tv);
- if (timevalcmp(&ib->deadline, &tv, <)) {
- ib_had_timeout(ib->ap);
- upd7210_wr(u, IMR1, 0);
- upd7210_wr(u, IMR2, 0);
- if (u->use_fifo) {
- bus_write_1(u->reg_res[0], imr3, 0x00);
- bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
- }
- ib->mode = BUSY;
- wakeup(&ib->buflen);
- }
- }
- if (ib->mode != IDLE)
- callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, arg);
- mtx_unlock(&u->mutex);
-}
-
-static void
-gpib_ib_wait_xfer(struct upd7210 *u, struct ibfoo *ib)
-{
- int i;
-
- mtx_assert(&u->mutex, MA_OWNED);
- while (ib->mode > BUSY) {
- i = msleep(&ib->buflen, &u->mutex,
- PZERO | PCATCH, "ibwxfr", 0);
- if (i == EINTR) {
- ib_set_errno(ib->ap, i);
- break;
- }
- if (u->rreg[ISR1] & IXR1_ERR) {
- ib_set_error(ib->ap, EABO); /* XXX ? */
- break;
- }
- }
- if ((u->rreg[ISR1] & IXR1_ENDRX) != 0) {
- ib->ap->__retval |= END;
- ib->ap->__ibsta |= END;
- }
- if ((u->rreg[ISR2] & IXR2_SRQI) != 0) {
- ib->ap->__retval |= SRQI;
- ib->ap->__ibsta |= SRQI;
- }
- ib->mode = BUSY;
- ib->buf = NULL;
- upd7210_wr(u, IMR1, 0);
- upd7210_wr(u, IMR2, 0);
- if (u->use_fifo)
- bus_write_1(u->reg_res[0], imr3, 0x00);
-}
-
-static void
-config_eos(struct upd7210 *u, struct handle *h)
-{
- int i;
-
- i = 0;
- if (h->eos & REOS) {
- upd7210_wr(u, EOSR, h->eos & 0xff);
- i |= AUXA_REOS;
- }
- if (h->eos & XEOS) {
- upd7210_wr(u, EOSR, h->eos & 0xff);
- i |= AUXA_XEOS;
- }
- if (h->eos & BIN)
- i |= AUXA_BIN;
- upd7210_wr(u, AUXRA, C_AUXA | i);
-}
-
-/*
- * Look up the handle, and set the deadline if the handle has a timeout.
- */
-static int
-gethandle(struct upd7210 *u, struct ibarg *ap, struct handle **hp)
-{
- struct ibfoo *ib;
- struct handle *h;
-
- KASSERT(ap->__field & __F_HANDLE, ("gethandle without __F_HANDLE"));
- ib = u->ibfoo;
- LIST_FOREACH(h, &ib->handles, list) {
- if (h->handle == ap->handle) {
- *hp = h;
- return (0);
- }
- }
- ib_set_error(ap, EARG);
- return (1);
-}
-
-static int
-pio_cmd(struct upd7210 *u, u_char *cmd, int len)
-{
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- if (ib->rdh != NULL || ib->wrh != NULL) {
- upd7210_take_ctrl_async(u);
- ib->rdh = NULL;
- ib->wrh = NULL;
- }
- mtx_lock(&u->mutex);
- ib->buf = cmd;
- ib->buflen = len;
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- ib->mode = FIFO_CMD;
- upd7210_wr(u, AUXMR, 0x51); /* holdoff immediately */
- bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
- bus_write_1(u->reg_res[0], cfg, 0x80); /* CMD, xfer OUT, 8-bit FIFO */
- bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */
- bus_write_1(u->reg_res[0], cnt0, -len);
- bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
- bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
- bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- } else {
- ib->mode = PIO_CMD;
- upd7210_wr(u, IMR2, IXR2_CO);
- gpib_ib_irq(u, 0);
- }
-
- gpib_ib_wait_xfer(u, ib);
-
- if (u->use_fifo)
- bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
-
- mtx_unlock(&u->mutex);
- return (len - ib->buflen);
-}
-
-static int
-pio_odata(struct upd7210 *u, u_char *data, int len)
-{
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- if (len == 0)
- return (0);
- mtx_lock(&u->mutex);
- ib->buf = data;
- ib->buflen = len;
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- ib->mode = FIFO_ODATA;
- bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
- if (ib->doeoi)
- bus_write_1(u->reg_res[0], cfg, 0x08); /* CCEN */
- else
- bus_write_1(u->reg_res[0], cfg, 0x00); /* xfer OUT, 8-bit FIFO */
- bus_write_1(u->reg_res[0], imr3, 0x19); /* STOP IE, NFF IE, DONE IE */
- bus_write_1(u->reg_res[0], cnt0, -len);
- bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
- bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
- bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- } else {
- ib->mode = PIO_ODATA;
- upd7210_wr(u, IMR1, IXR1_DO);
- }
-
- gpib_ib_wait_xfer(u, ib);
-
- if (u->use_fifo)
- bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
-
- mtx_unlock(&u->mutex);
- return (len - ib->buflen);
-}
-
-static int
-pio_idata(struct upd7210 *u, u_char *data, int len)
-{
- struct ibfoo *ib;
-
- ib = u->ibfoo;
-
- mtx_lock(&u->mutex);
- ib->buf = data;
- ib->buflen = len;
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- ib->mode = FIFO_IDATA;
- bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
- bus_write_1(u->reg_res[0], cfg, 0x20); /* xfer IN, 8-bit FIFO */
- bus_write_1(u->reg_res[0], cnt0, -len);
- bus_write_1(u->reg_res[0], cnt1, (-len) >> 8);
- bus_write_1(u->reg_res[0], cnt2, (-len) >> 16);
- bus_write_1(u->reg_res[0], cnt3, (-len) >> 24);
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- upd7210_wr(u, AUXMR, AUXMR_RFD);
- bus_write_1(u->reg_res[0], imr3, 0x15); /* STOP IE, NEF IE, DONE IE */
- } else {
- ib->mode = PIO_IDATA;
- upd7210_wr(u, IMR1, IXR1_DI);
- }
-
- gpib_ib_wait_xfer(u, ib);
-
- if (u->use_fifo)
- bus_write_1(u->reg_res[0], cmdr, 0x08); /* STOP */
-
- mtx_unlock(&u->mutex);
- return (len - ib->buflen);
-}
-
-static int
-dma_idata(struct upd7210 *u, u_char *data, int len)
-{
- int j;
- struct ibfoo *ib;
-
- KASSERT(u->dmachan >= 0, ("Bogus dmachan %d", u->dmachan));
- ib = u->ibfoo;
- ib->mode = DMA_IDATA;
- isa_dmastart(ISADMA_READ, data, len, u->dmachan);
- mtx_lock(&u->mutex);
- upd7210_wr(u, IMR1, IXR1_ENDRX);
- upd7210_wr(u, IMR2, IMR2_DMAI);
- gpib_ib_wait_xfer(u, ib);
- mtx_unlock(&u->mutex);
- j = isa_dmastatus(u->dmachan);
- isa_dmadone(ISADMA_READ, data, len, u->dmachan);
- return (len - j);
-}
-
-static int
-ib_send_msg(struct ibfoo *ib, int msg)
-{
- u_char buf[10];
- int i, j;
-
- i = 0;
- buf[i++] = UNT;
- buf[i++] = UNL;
- buf[i++] = LAD | ib->h->pad;
- if (ib->h->sad)
- buf[i++] = LAD | TAD | ib->h->sad;
- buf[i++] = TAD | 0;
- buf[i++] = msg;
- j = pio_cmd(ib->u, buf, i);
- if (i != j)
- ib_set_error(ib->ap, EABO); /* XXX ? */
- return (0);
-}
-
-static int
-ibask(struct ibfoo *ib)
-{ /* XXX */
-
- ibdebug = ib->ap->option;
- return (0);
-}
-
-#define ibbna NULL
-#define ibcac NULL
-
-static int
-ibclr(struct ibfoo *ib)
-{
-
- return (ib_send_msg(ib, SDC));
-}
-
-#define ibcmd NULL
-#define ibcmda NULL
-#define ibconfig NULL
-
-static int
-ibdev(struct ibfoo *ib)
-{ /* TBD */
- struct handle *h;
-
- h = malloc(sizeof *h, M_IBFOO, M_ZERO | M_WAITOK);
- h->handle = alloc_unr(ib->unrhdr);
- h->kind = H_DEV;
- h->pad = ib->ap->pad;
- h->sad = ib->ap->sad;
- h->timeout = timeouts[ib->ap->tmo];
- h->eot = ib->ap->eot;
- h->eos = ib->ap->eos;
- mtx_lock(&ib->u->mutex);
- LIST_INSERT_HEAD(&ib->handles, h, list);
- mtx_unlock(&ib->u->mutex);
- ib->ap->__retval = h->handle;
- return (0);
-}
-
-#define ibdiag NULL
-
-static int
-ibdma(struct ibfoo *ib)
-{
-
- if (ib->u->dmachan < 0 && ib->ap->v)
- return (ib_set_error(ib->ap, EARG));
- ib->h->dma = ib->ap->v;
- return (0);
-}
-
-static int
-ibeos(struct ibfoo *ib)
-{
-
- ib->ap->__iberr = ib->h->eos;
- ib->h->eos = ib->ap->eos;
- if (ib->rdh == ib->h)
- config_eos(ib->u, ib->h);
- return (0);
-}
-
-static int
-ibeot(struct ibfoo *ib)
-{
-
- ib->h->eot = ib->ap->eot;
- return (0);
-}
-
-#define ibevent NULL
-#define ibfind NULL
-#define ibgts NULL
-#define ibist NULL
-#define iblines NULL
-#define ibllo NULL
-#define ibln NULL
-
-static int
-ibloc(struct ibfoo *ib)
-{ /* XXX */
-
- if (ib->h->kind == H_BOARD)
- return (EOPNOTSUPP); /* XXX */
- return (ib_send_msg(ib, GTL));
-}
-
-static int
-ibonl(struct ibfoo *ib)
-{ /* XXX */
-
- if (ib->ap->v)
- return (EOPNOTSUPP); /* XXX */
- mtx_lock(&ib->u->mutex);
- LIST_REMOVE(ib->h, list);
- mtx_unlock(&ib->u->mutex);
- free(ib->h, M_IBFOO);
- ib->h = NULL;
- return (0);
-}
-
-static int
-ibpad(struct ibfoo *ib)
-{
-
- ib->h->pad = ib->ap->pad;
- return (0);
-}
-
-#define ibpct NULL
-#define ibpoke NULL
-#define ibppc NULL
-
-static int
-ibrd(struct ibfoo *ib)
-{ /* TBD */
- u_char buf[10], *bp;
- int i, j, error, bl, bc;
- u_char *dp;
-
- if (ib->h->kind == H_BOARD)
- return (EOPNOTSUPP); /* XXX */
- bl = ib->ap->cnt;
- if (bl > PAGE_SIZE)
- bl = PAGE_SIZE;
- bp = malloc(bl, M_IBFOO, M_WAITOK);
-
- if (ib->rdh != ib->h) {
- i = 0;
- buf[i++] = UNT;
- buf[i++] = UNL;
- buf[i++] = LAD | 0;
- buf[i++] = TAD | ib->h->pad;
- if (ib->h->sad)
- buf[i++] = ib->h->sad;
- i = pio_cmd(ib->u, buf, i);
- config_eos(ib->u, ib->h);
- ib->rdh = ib->h;
- ib->wrh = NULL;
- }
- upd7210_goto_standby(ib->u);
- dp = ib->ap->buffer;
- bc = ib->ap->cnt;
- error = 0;
- while (bc > 0 && ib->ap->__iberr == 0) {
- j = imin(bc, PAGE_SIZE);
- if (ib->h->dma)
- i = dma_idata(ib->u, bp, j);
- else
- i = pio_idata(ib->u, bp, j);
- error = copyout(bp, dp , i);
- if (error)
- break;
- ib->ap->__ibcnt += i;
- if (i != j)
- break;
- bc -= i;
- dp += i;
- }
- upd7210_take_ctrl_async(ib->u);
- free(bp, M_IBFOO);
- return (error);
-}
-
-#define ibrda NULL
-#define ibrdf NULL
-#define ibrdkey NULL
-#define ibrpp NULL
-#define ibrsc NULL
-#define ibrsp NULL
-#define ibrsv NULL
-
-static int
-ibsad(struct ibfoo *ib)
-{
-
- ib->h->sad = ib->ap->sad;
- return (0);
-}
-
-#define ibsgnl NULL
-
-static int
-ibsic(struct ibfoo *ib)
-{ /* TBD */
-
- upd7210_wr(ib->u, AUXMR, AUXMR_SIFC);
- DELAY(100);
- upd7210_wr(ib->u, AUXMR, AUXMR_CIFC);
- return (0);
-}
-
-#define ibsre NULL
-#define ibsrq NULL
-#define ibstop NULL
-
-static int
-ibtmo(struct ibfoo *ib)
-{
-
- ib->h->timeout = timeouts[ib->ap->tmo];
- return (0);
-}
-
-#define ibtrap NULL
-
-static int
-ibtrg(struct ibfoo *ib)
-{
-
- return (ib_send_msg(ib, GET));
-}
-
-#define ibwait NULL
-
-static int
-ibwrt(struct ibfoo *ib)
-{ /* XXX */
- u_char buf[10], *bp;
- int i;
-
- if (ib->h->kind == H_BOARD)
- return (EOPNOTSUPP);
- bp = malloc(ib->ap->cnt, M_IBFOO, M_WAITOK);
- /* XXX: bigger than PAGE_SIZE handling */
- i = copyin(ib->ap->buffer, bp, ib->ap->cnt);
- if (i) {
- free(bp, M_IBFOO);
- return (i);
- }
- if (ib->wrh != ib->h) {
- i = 0;
- buf[i++] = UNT;
- buf[i++] = UNL;
- buf[i++] = LAD | ib->h->pad;
- if (ib->h->sad)
- buf[i++] = LAD | TAD | ib->h->sad;
- buf[i++] = TAD | 0;
- i = pio_cmd(ib->u, buf, i);
- ib->rdh = NULL;
- ib->wrh = ib->h;
- config_eos(ib->u, ib->h);
- }
- upd7210_goto_standby(ib->u);
- ib->doeoi = ib->h->eot;
- i = pio_odata(ib->u, bp, ib->ap->cnt);
- upd7210_take_ctrl_async(ib->u);
- ib->ap->__ibcnt = i;
- free(bp, M_IBFOO);
- return (0);
-}
-
-#define ibwrta NULL
-#define ibwrtf NULL
-#define ibwrtkey NULL
-#define ibxtrc NULL
-
-static struct ibhandler {
- const char *name;
- enum h_kind kind;
- ibhandler_t *func;
- u_int args;
-} ibhandlers[] = {
- [__ID_IBASK] = { "ibask", H_EITHER, ibask, __F_HANDLE | __F_OPTION | __F_RETVAL },
- [__ID_IBBNA] = { "ibbna", H_DEV, ibbna, __F_HANDLE | __F_BDNAME },
- [__ID_IBCAC] = { "ibcac", H_BOARD, ibcac, __F_HANDLE | __F_V },
- [__ID_IBCLR] = { "ibclr", H_DEV, ibclr, __F_HANDLE },
- [__ID_IBCMD] = { "ibcmd", H_BOARD, ibcmd, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBCMDA] = { "ibcmda", H_BOARD, ibcmda, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBCONFIG] = { "ibconfig", H_EITHER, ibconfig, __F_HANDLE | __F_OPTION | __F_VALUE },
- [__ID_IBDEV] = { "ibdev", 0, ibdev, __F_BOARDID | __F_PAD | __F_SAD | __F_TMO | __F_EOT | __F_EOS },
- [__ID_IBDIAG] = { "ibdiag", H_EITHER, ibdiag, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBDMA] = { "ibdma", H_EITHER, ibdma, __F_HANDLE | __F_V },
- [__ID_IBEOS] = { "ibeos", H_EITHER, ibeos, __F_HANDLE | __F_EOS },
- [__ID_IBEOT] = { "ibeot", H_EITHER, ibeot, __F_HANDLE | __F_EOT },
- [__ID_IBEVENT] = { "ibevent", H_BOARD, ibevent, __F_HANDLE | __F_EVENT },
- [__ID_IBFIND] = { "ibfind", 0, ibfind, __F_BDNAME },
- [__ID_IBGTS] = { "ibgts", H_BOARD, ibgts, __F_HANDLE | __F_V },
- [__ID_IBIST] = { "ibist", H_BOARD, ibist, __F_HANDLE | __F_V },
- [__ID_IBLINES] = { "iblines", H_BOARD, iblines, __F_HANDLE | __F_LINES },
- [__ID_IBLLO] = { "ibllo", H_EITHER, ibllo, __F_HANDLE },
- [__ID_IBLN] = { "ibln", H_BOARD, ibln, __F_HANDLE | __F_PADVAL | __F_SADVAL | __F_LISTENFLAG },
- [__ID_IBLOC] = { "ibloc", H_EITHER, ibloc, __F_HANDLE },
- [__ID_IBONL] = { "ibonl", H_EITHER, ibonl, __F_HANDLE | __F_V },
- [__ID_IBPAD] = { "ibpad", H_EITHER, ibpad, __F_HANDLE | __F_PAD },
- [__ID_IBPCT] = { "ibpct", H_DEV, ibpct, __F_HANDLE },
- [__ID_IBPOKE] = { "ibpoke", H_EITHER, ibpoke, __F_HANDLE | __F_OPTION | __F_VALUE },
- [__ID_IBPPC] = { "ibppc", H_EITHER, ibppc, __F_HANDLE | __F_V },
- [__ID_IBRD] = { "ibrd", H_EITHER, ibrd, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRDA] = { "ibrda", H_EITHER, ibrda, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRDF] = { "ibrdf", H_EITHER, ibrdf, __F_HANDLE | __F_FLNAME },
- [__ID_IBRDKEY] = { "ibrdkey", H_EITHER, ibrdkey, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBRPP] = { "ibrpp", H_EITHER, ibrpp, __F_HANDLE | __F_PPR },
- [__ID_IBRSC] = { "ibrsc", H_BOARD, ibrsc, __F_HANDLE | __F_V },
- [__ID_IBRSP] = { "ibrsp", H_DEV, ibrsp, __F_HANDLE | __F_SPR },
- [__ID_IBRSV] = { "ibrsv", H_EITHER, ibrsv, __F_HANDLE | __F_V },
- [__ID_IBSAD] = { "ibsad", H_EITHER, ibsad, __F_HANDLE | __F_SAD },
- [__ID_IBSGNL] = { "ibsgnl", H_EITHER, ibsgnl, __F_HANDLE | __F_V },
- [__ID_IBSIC] = { "ibsic", H_BOARD, ibsic, __F_HANDLE },
- [__ID_IBSRE] = { "ibsre", H_BOARD, ibsre, __F_HANDLE | __F_V },
- [__ID_IBSRQ] = { "ibsrq", H_EITHER, ibsrq, __F_FUNC },
- [__ID_IBSTOP] = { "ibstop", H_EITHER, ibstop, __F_HANDLE },
- [__ID_IBTMO] = { "ibtmo", H_EITHER, ibtmo, __F_HANDLE | __F_TMO },
- [__ID_IBTRAP] = { "ibtrap", H_EITHER, ibtrap, __F_MASK | __F_MODE },
- [__ID_IBTRG] = { "ibtrg", H_DEV, ibtrg, __F_HANDLE },
- [__ID_IBWAIT] = { "ibwait", H_EITHER, ibwait, __F_HANDLE | __F_MASK },
- [__ID_IBWRT] = { "ibwrt", H_EITHER, ibwrt, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBWRTA] = { "ibwrta", H_EITHER, ibwrta, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBWRTF] = { "ibwrtf", H_EITHER, ibwrtf, __F_HANDLE | __F_FLNAME },
- [__ID_IBWRTKEY] = { "ibwrtkey", H_EITHER, ibwrtkey, __F_HANDLE | __F_BUFFER | __F_CNT },
- [__ID_IBXTRC] = { "ibxtrc", H_EITHER, ibxtrc, __F_HANDLE | __F_BUFFER | __F_CNT },
-};
-
-static const u_int max_ibhandler = sizeof ibhandlers / sizeof ibhandlers[0];
-
-static void
-ib_dump_args(struct ibhandler *ih, struct ibarg *ap)
-{
-
- if (ih->name != NULL)
- printf("%s(", ih->name);
- else
- printf("ibinvalid(");
- printf("[0x%x]", ap->__field);
- if (ap->__field & __F_HANDLE) printf(" handle=%d", ap->handle);
- if (ap->__field & __F_EOS) printf(" eos=0x%x", ap->eos);
- if (ap->__field & __F_EOT) printf(" eot=%d", ap->eot);
- if (ap->__field & __F_TMO) printf(" tmo=%d", ap->tmo);
- if (ap->__field & __F_PAD) printf(" pad=0x%x", ap->pad);
- if (ap->__field & __F_SAD) printf(" sad=0x%x", ap->sad);
- if (ap->__field & __F_BUFFER) printf(" buffer=%p", ap->buffer);
- if (ap->__field & __F_CNT) printf(" cnt=%ld", ap->cnt);
- if (ap->__field & __F_V) printf(" v=%d/0x%x", ap->v, ap->v);
- /* XXX more ... */
- printf(")\n");
-}
-
-static int
-gpib_ib_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
- struct ibfoo *ib;
- int error = 0;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- if (u->busy) {
- mtx_unlock(&u->mutex);
- return (EBUSY);
- }
- u->busy = 1;
- mtx_unlock(&u->mutex);
-
- if (u->dmachan >= 0) {
- error = isa_dma_acquire(u->dmachan);
- if (!error) {
- error = isa_dma_init(u->dmachan, PAGE_SIZE, M_WAITOK);
- if (error)
- isa_dma_release(u->dmachan);
- }
- }
-
- if (error) {
- mtx_lock(&u->mutex);
- u->busy = 0;
- mtx_unlock(&u->mutex);
- return (error);
- }
-
- ib = malloc(sizeof *ib, M_IBFOO, M_WAITOK | M_ZERO);
- LIST_INIT(&ib->handles);
- callout_init(&ib->callout, CALLOUT_MPSAFE);
- ib->unrhdr = new_unrhdr(0, INT_MAX, NULL);
- dev->si_drv2 = ib;
- ib->u = u;
- u->ibfoo = ib;
- u->irq = gpib_ib_irq;
-
- upd7210_wr(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- DELAY(1000);
- upd7210_wr(u, IMR1, 0x00);
- upd7210_wr(u, IMR2, 0x00);
- upd7210_wr(u, SPMR, 0x00);
- upd7210_wr(u, ADR, 0x00);
- upd7210_wr(u, ADR, ADR_ARS | ADR_DL | ADR_DT);
- upd7210_wr(u, ADMR, ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1);
- upd7210_wr(u, EOSR, 0x00);
- upd7210_wr(u, AUXMR, C_ICR | 8);
- upd7210_wr(u, AUXMR, C_PPR | PPR_U);
- upd7210_wr(u, AUXMR, C_AUXA);
- upd7210_wr(u, AUXMR, C_AUXB + 3);
- upd7210_wr(u, AUXMR, C_AUXE + 0);
- upd7210_wr(u, AUXMR, AUXMR_PON);
- if (u->use_fifo) {
- bus_write_1(u->reg_res[0], imr3, 0x00);
- bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft reset */
- bus_write_1(u->reg_res[0], cmdr, 0x03); /* set system
- * controller bit */
- }
- upd7210_wr(u, AUXMR, AUXMR_CIFC);
- DELAY(100);
- upd7210_wr(u, AUXMR, AUXMR_SIFC);
- upd7210_wr(u, AUXMR, AUXMR_SREN);
- return (0);
-}
-
-static int
-gpib_ib_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
- struct ibfoo *ib;
-
- u = dev->si_drv1;
- ib = dev->si_drv2;
- /* XXX: assert pointer consistency */
-
- u->ibfoo = NULL;
- /* XXX: free handles */
- dev->si_drv2 = NULL;
- free(ib, M_IBFOO);
-
- if (u->dmachan >= 0) {
- isa_dma_release(u->dmachan);
- }
- mtx_lock(&u->mutex);
- u->busy = 0;
- ibdebug = 0;
- upd7210_wr(u, IMR1, 0x00);
- upd7210_wr(u, IMR2, 0x00);
- if (u->use_fifo) {
- bus_write_1(u->reg_res[0], imr3, 0x00);
- bus_write_1(u->reg_res[0], cmdr, 0x02); /* clear system
- * controller bit */
- }
- upd7210_wr(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- mtx_unlock(&u->mutex);
- return (0);
-}
-
-static int
-gpib_ib_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
-{
- struct ibarg *ap;
- struct ibhandler *ih;
- struct handle *h;
- struct upd7210 *u;
- struct ibfoo *ib;
- int error;
- struct timeval deadline, tv;
-
- u = dev->si_drv1;
- ib = u->ibfoo;
-
- /* We only support a single ioctl, everything else is a mistake */
- if (cmd != GPIB_IBFOO)
- return (ENOIOCTL);
-
- /* Check the identifier and field-bitmap in the arguments. */
- ap = (void *)data;
- if (ap->__ident < 0 || ap->__ident >= max_ibhandler)
- return (EINVAL);
- ih = &ibhandlers[ap->__ident];
- if (ap->__field != ih->args)
- return (EINVAL);
-
- if (ibdebug)
- ib_dump_args(ih, ap);
-
- if (ih->func == NULL)
- return (EOPNOTSUPP);
-
- ap->__iberr = 0;
- ap->__ibsta = 0;
- ap->__ibcnt = 0;
- ap->__retval = 0;
-
- if (ap->__field & __F_TMO) {
- if (ap->tmo < 0 || ap->tmo >= max_timeouts)
- return (ib_set_error(ap, EARG));
- }
-
- if (ap->__field & __F_EOS) {
- if ((ap->eos & ~(REOS | XEOS | BIN | 0xff)) ||
- ((ap->eos & (BIN | 0x80)) == 0x80))
- return (ib_set_error(ap, EARG));
- }
- if (ap->__field & __F_PAD) {
- if (ap->pad < 0 || ap->pad > 30)
- return (ib_set_error(ap, EARG));
- }
- if (ap->__field & __F_SAD) {
- if (ap->sad != 0 && (ap->sad < 0x60 || ap->sad > 126))
- return (ib_set_error(ap, EARG));
- }
-
-
- mtx_lock(&u->mutex);
-
-
- /* Find the handle, if any */
- h = NULL;
- if ((ap->__field & __F_HANDLE) && gethandle(u, ap, &h)) {
- mtx_unlock(&u->mutex);
- return (0);
- }
-
- /* Check that the handle is the right kind */
- if (h != NULL && !(h->kind & ih->kind)) {
- mtx_unlock(&u->mutex);
- return (ib_set_error(ap, EARG));
- }
-
- /* Set up handle and deadline */
- if (h != NULL && timevalisset(&h->timeout)) {
- getmicrouptime(&deadline);
- timevaladd(&deadline, &h->timeout);
- } else {
- timevalclear(&deadline);
- }
-
- /* Wait for the card to be(come) available, respect deadline */
- while(u->busy != 1) {
- error = msleep(ib, &u->mutex,
- PZERO | PCATCH, "gpib_ibioctl", hz / 10);
- if (error == 0)
- continue;
- mtx_unlock(&u->mutex);
- if (error == EINTR)
- return(ib_set_error(ap, EABO));
- if (error == EWOULDBLOCK && timevalisset(&deadline)) {
- getmicrouptime(&tv);
- if (timevalcmp(&deadline, &tv, <))
- return(ib_had_timeout(ap));
- }
- mtx_lock(&u->mutex);
- }
- u->busy = 2;
- mtx_unlock(&u->mutex);
-
- /* Hand over deadline handling to the callout routine */
- ib->ap = ap;
- ib->h = h;
- ib->mode = BUSY;
- ib->deadline = deadline;
- callout_reset(&ib->callout, hz / 5, gpib_ib_timeout, u);
-
- error = ih->func(ib);
-
- /* Release card */
- ib->mode = IDLE;
- ib->ap = NULL;
- ib->h = NULL;
- timevalclear(&deadline);
- callout_stop(&ib->callout);
-
- mtx_lock(&u->mutex);
- u->busy = 1;
- wakeup(ib);
- mtx_unlock(&u->mutex);
-
- if (error)
- return(ib_set_errno(ap, error));
- return (0);
-}
-
-struct cdevsw gpib_ib_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "gpib_ib",
- .d_open = gpib_ib_open,
- .d_ioctl = gpib_ib_ioctl,
- .d_close = gpib_ib_close,
-};
diff --git a/sys/dev/ieee488/ibfoo_int.h b/sys/dev/ieee488/ibfoo_int.h
deleted file mode 100644
index 28f7289..0000000
--- a/sys/dev/ieee488/ibfoo_int.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp
- * 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.
- *
- * This file defines the ABI between the userland gpib library and the
- * kernel. This file should not be used anywhere else.
- *
- * $FreeBSD$
- */
-
-#include <sys/ioccom.h>
-
-typedef void ibsrq_t(void);
-enum ibfoo_id {
- __ID_INVALID = 0,
- __ID_IBASK,
- __ID_IBBNA,
- __ID_IBCAC,
- __ID_IBCLR,
- __ID_IBCMD,
- __ID_IBCMDA,
- __ID_IBCONFIG,
- __ID_IBDEV,
- __ID_IBDIAG,
- __ID_IBDMA,
- __ID_IBEOS,
- __ID_IBEOT,
- __ID_IBEVENT,
- __ID_IBFIND,
- __ID_IBGTS,
- __ID_IBIST,
- __ID_IBLINES,
- __ID_IBLLO,
- __ID_IBLN,
- __ID_IBLOC,
- __ID_IBONL,
- __ID_IBPAD,
- __ID_IBPCT,
- __ID_IBPOKE,
- __ID_IBPPC,
- __ID_IBRD,
- __ID_IBRDA,
- __ID_IBRDF,
- __ID_IBRDKEY,
- __ID_IBRPP,
- __ID_IBRSC,
- __ID_IBRSP,
- __ID_IBRSV,
- __ID_IBSAD,
- __ID_IBSGNL,
- __ID_IBSIC,
- __ID_IBSRE,
- __ID_IBSRQ,
- __ID_IBSTOP,
- __ID_IBTMO,
- __ID_IBTRAP,
- __ID_IBTRG,
- __ID_IBWAIT,
- __ID_IBWRT,
- __ID_IBWRTA,
- __ID_IBWRTF,
- __ID_IBWRTKEY,
- __ID_IBXTRC
-};
-
-#define __F_HANDLE (1 << 0)
-#define __F_SPR (1 << 1)
-#define __F_BUFFER (1 << 2)
-#define __F_RETVAL (1 << 3)
-#define __F_BDNAME (1 << 4)
-#define __F_MASK (1 << 5)
-#define __F_PADVAL (1 << 6)
-#define __F_SADVAL (1 << 7)
-#define __F_CNT (1 << 8)
-#define __F_TMO (1 << 9)
-#define __F_EOS (1 << 10)
-#define __F_PPR (1 << 11)
-#define __F_EOT (1 << 12)
-#define __F_V (1 << 13)
-#define __F_VALUE (1 << 14)
-#define __F_SAD (1 << 15)
-#define __F_BOARDID (1 << 16)
-#define __F_OPTION (1 << 17)
-#define __F_FLNAME (1 << 18)
-#define __F_FUNC (1 << 19)
-#define __F_LINES (1 << 20)
-#define __F_PAD (1 << 21)
-#define __F_MODE (1 << 22)
-#define __F_LISTENFLAG (1 << 23)
-#define __F_EVENT (1 << 24)
-
-struct ibarg {
- enum ibfoo_id __ident;
- unsigned int __field;
- int __retval;
- int __ibsta;
- int __iberr;
- int __ibcnt;
- int handle;
- char * spr;
- void * buffer;
- int * retval;
- char * bdname;
- int mask;
- int padval;
- int sadval;
- long cnt;
- int tmo;
- int eos;
- char * ppr;
- int eot;
- int v;
- int value;
- int sad;
- int boardID;
- int option;
- char * flname;
- ibsrq_t * func;
- short * lines;
- int pad;
- int mode;
- short * listenflag;
- short * event;
-};
-
-#define GPIB_IBFOO _IOWR(4, 0, struct ibarg)
diff --git a/sys/dev/ieee488/pcii.c b/sys/dev/ieee488/pcii.c
deleted file mode 100644
index 833ec91..0000000
--- a/sys/dev/ieee488/pcii.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
- * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
- * 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.
- *
- * Driver for GPIB cards based on NEC µPD7210 and compatibles.
- *
- * This driver just hooks up to the hardware and leaves all the interesting
- * stuff to upd7210.c.
- *
- * Supported hardware:
- * PCIIA compatible cards.
- *
- * Tested and known working:
- * "B&C Microsystems PC488A-0"
- * "National Instruments GPIB-PCII/PCIIA" (in PCIIa mode)
- * "Axiom AX5488"
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-#include <isa/isavar.h>
-
-#define UPD7210_HW_DRIVER
-#include <dev/ieee488/upd7210.h>
-
-struct pcii_softc {
- int foo;
- struct resource *res[11];
- void *intr_handler;
- struct upd7210 upd7210;
-};
-
-static devclass_t pcii_devclass;
-
-static int pcii_probe(device_t dev);
-static int pcii_attach(device_t dev);
-
-static device_method_t pcii_methods[] = {
- DEVMETHOD(device_probe, pcii_probe),
- DEVMETHOD(device_attach, pcii_attach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- { 0, 0 }
-};
-
-static struct resource_spec pcii_res_spec[] = {
- { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE},
- { SYS_RES_DRQ, 0, RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL},
- { SYS_RES_IOPORT, 0, RF_ACTIVE},
- { SYS_RES_IOPORT, 1, RF_ACTIVE},
- { SYS_RES_IOPORT, 2, RF_ACTIVE},
- { SYS_RES_IOPORT, 3, RF_ACTIVE},
- { SYS_RES_IOPORT, 4, RF_ACTIVE},
- { SYS_RES_IOPORT, 5, RF_ACTIVE},
- { SYS_RES_IOPORT, 6, RF_ACTIVE},
- { SYS_RES_IOPORT, 7, RF_ACTIVE},
- { SYS_RES_IOPORT, 8, RF_ACTIVE | RF_SHAREABLE},
- { -1, 0, 0 }
-};
-
-static driver_t pcii_driver = {
- "pcii",
- pcii_methods,
- sizeof(struct pcii_softc),
-};
-
-static int
-pcii_probe(device_t dev)
-{
- int rid, i, j;
- u_long start, count, addr;
- int error = 0;
- struct pcii_softc *sc;
-
- device_set_desc(dev, "PCII IEEE-4888 controller");
- sc = device_get_softc(dev);
-
- rid = 0;
- if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0)
- return ENXIO;
- /*
- * The PCIIA decodes a fixed pattern of 0x2e1 for the lower 10
- * address bits A0 ... A9. Bits A10 through A12 are used by
- * the µPD7210 register select lines. This makes the
- * individual 7210 register being 0x400 bytes apart in the ISA
- * bus address space. Address bits A13 and A14 are compared
- * to a DIP switch setting on the card, allowing for up to 4
- * different cards being installed (at base addresses 0x2e1,
- * 0x22e1, 0x42e1, and 0x62e1, respectively). A15 has been
- * used to select an optional on-board time-of-day clock chip
- * (MM58167A) on the original PCIIA rather than the µPD7210
- * (which is not implemented on later boards). The
- * documentation states the respective addresses for that chip
- * should be handled as reserved addresses, which we don't do
- * (right now). Finally, the IO addresses 0x2f0 ... 0x2f7 for
- * a "special interrupt handling feature" (re-enable
- * interrupts so the IRQ can be shared).
- *
- * Usually, the user will only set the base address in the
- * device hints, so we handle the rest here.
- *
- * (Source: GPIB-PCIIA Technical Reference Manual, September
- * 1989 Edition, National Instruments.)
- */
- if ((start & 0x3ff) != 0x2e1) {
- if (bootverbose)
- printf("pcii_probe: PCIIA base address 0x%lx not "
- "0x2e1/0x22e1/0x42e1/0x62e1\n",
- start);
- return (ENXIO);
- }
-
- for (rid = 0, addr = start; rid < 8; rid++, addr += 0x400) {
- if (bus_set_resource(dev, SYS_RES_IOPORT, rid, addr, 1) != 0) {
- printf("pcii_probe: could not set IO port 0x%lx\n",
- addr);
- return (ENXIO);
- }
- }
- if (bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &count) != 0) {
- printf("pcii_probe: cannot obtain IRQ level\n");
- return ENXIO;
- }
- if (start > 7) {
- printf("pcii_probe: IRQ level %lu too high\n", start);
- return ENXIO;
- }
-
- if (bus_set_resource(dev, SYS_RES_IOPORT, 8, 0x2f0 + start, 1) != 0) {
- printf("pcii_probe: could not set IO port 0x%3lx\n",
- 0x2f0 + start);
- return (ENXIO);
- }
-
- error = bus_alloc_resources(dev, pcii_res_spec, sc->res);
- if (error) {
- printf("pcii_probe: Could not allocate resources\n");
- return (error);
- }
- error = ENXIO;
- /*
- * Perform some basic tests on the µPD7210 registers. At
- * least *some* register must read different from 0x00 or
- * 0xff.
- */
- for (i = 0; i < 8; i++) {
- j = bus_read_1(sc->res[2 + i], 0);
- if (j != 0x00 && j != 0xff)
- error = 0;
- }
- /* SPSR/SPMR read/write test */
- if (!error) {
- bus_write_1(sc->res[2 + 3], 0, 0x55);
- if (bus_read_1(sc->res[2 + 3], 0) != 0x55)
- error = ENXIO;
- }
- if (!error) {
- bus_write_1(sc->res[2 + 3], 0, 0xaa);
- if (bus_read_1(sc->res[2 + 3], 0) != 0xaa)
- error = ENXIO;
- }
- if (error)
- printf("pcii_probe: probe failure\n");
-
- bus_release_resources(dev, pcii_res_spec, sc->res);
- return (error);
-}
-
-static int
-pcii_attach(device_t dev)
-{
- struct pcii_softc *sc;
- u_long start, count;
- int unit;
- int rid;
- int error = 0;
-
- unit = device_get_unit(dev);
- sc = device_get_softc(dev);
- memset(sc, 0, sizeof *sc);
-
- device_set_desc(dev, "PCII IEEE-4888 controller");
-
- if (bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &count) != 0) {
- printf("pcii_attach: cannot obtain IRQ number\n");
- return ENXIO;
- }
-
- error = bus_alloc_resources(dev, pcii_res_spec, sc->res);
- if (error)
- return (error);
-
- error = bus_setup_intr(dev, sc->res[0],
- INTR_TYPE_MISC | INTR_MPSAFE, NULL,
- upd7210intr, &sc->upd7210, &sc->intr_handler);
- if (error) {
- bus_release_resources(dev, pcii_res_spec, sc->res);
- return (error);
- }
-
- for (rid = 0; rid < 8; rid++) {
- sc->upd7210.reg_res[rid] = sc->res[2 + rid];
- sc->upd7210.reg_offset[rid] = 0;
- }
- sc->upd7210.irq_clear_res = sc->res[10];
- sc->upd7210.use_fifo = 0;
-
- if (sc->res[1] == NULL)
- sc->upd7210.dmachan = -1;
- else
- sc->upd7210.dmachan = rman_get_start(sc->res[1]);
-
- upd7210attach(&sc->upd7210);
- device_printf(dev, "attached gpib%d\n", sc->upd7210.unit);
-
- return (0);
-}
-
-DRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0);
-DRIVER_MODULE(pcii, acpi, pcii_driver, pcii_devclass, 0, 0);
diff --git a/sys/dev/ieee488/tnt4882.c b/sys/dev/ieee488/tnt4882.c
deleted file mode 100644
index 4b69d0d..0000000
--- a/sys/dev/ieee488/tnt4882.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp
- * Copyright (c) 2010 Joerg Wunsch
- * 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <machine/stdarg.h>
-#include <sys/rman.h>
-
-/* vtophys */
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/pmap.h>
-
-#define UPD7210_HW_DRIVER 1
-#include <dev/ieee488/upd7210.h>
-#include <dev/ieee488/tnt4882.h>
-
-struct tnt_softc {
- int foo;
- struct upd7210 upd7210;
-
- struct resource *res[3];
- void *intr_handler;
-};
-
-static struct resource_spec tnt_res_spec[] = {
- { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE},
- { SYS_RES_MEMORY, PCIR_BAR(1), RF_ACTIVE},
- { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE},
- { -1, 0 }
-};
-
-struct tst {
- enum {RD, WT, xDELAY, END}
- action;
- enum tnt4882reg reg;
- uint8_t val;
-};
-
-/*
- * From NI Application note 095:
- * Writing Functional Self-Tests for the TNT4882 GPIB Interface Chip
- * XXX: fill in the rest ?
- */
-static struct tst tst_reset[] = {
- {WT, tauxcr, 0x80}, /* chip reset if in 9914 mode */
- {WT, auxmr, 0x80}, /* swrst if swapped */
- {WT, tauxcr, 0x99}, /* switch to 7210 mode */
- {WT, auxmr, 0x99}, /* switch to 7210 mode if swapped */
- {WT, auxmr, 0x02}, /* execute chip reset */
- {WT, keyreg, 0x00}, /* important! clear the swap bit */
- {WT, eosr, 0x00}, /* clear EOS register */
- {WT, cdor, 0x00}, /* clear data lines */
- {WT, imr1, 0x00}, /* disable all interrupts */
- {WT, imr2, 0x00},
- {WT, imr0, 0x80},
- {WT, adr, 0x80},
- {WT, adr, 0x00},
- {WT, admr, 0x00}, /* clear addressing modes */
- {WT, auxmr, 0x00}, /* release from idle state with pon */
- {WT, auxmr, 0x60}, /* reset ppr */
- {WT, bcr, 0x00}, /* reset bcr */
- {WT, misc, 0x04}, /* set wrap plug bit */
- {WT, cmdr, 0xB2}, /* issue soft reset */
- {WT, hssel, 0x00}, /* select two-chip mode */
- {END, 0, 0}
-};
-
-static struct tst tst_read_reg[] = {
- {RD, isr1, 0x00}, /* Verify mask registers are clear */
- {RD, isr2, 0x00},
- {RD, adsr, 0x40}, /* Verify ATN is not asserted */
- {RD, adr0, 0x00}, /* Verify Primary address not set */
- {RD, adr1, 0x00}, /* Verify Secondary address not set */
- {RD, sts1, 0x8B}, /* Verify DONE, STOP, HALT, and GSYNC set */
- {RD, isr3, 0x19}, /* Verify STOP, Not Full FIFO, & DONE set */
- {RD, sts2, 0x9A}, /* Verify FIFO A/B is empty */
- {RD, sasr, 0x00}, /* Verify clear */
- {RD, isr0, 0x01}, /* Verify SYNC bit is set */
- {END, 0, 0}
-};
-
-static struct tst tst_bsr_dcr[] = {
- {WT, bcr, 0x55}, /* Set DAV, NRFD, SRQ, and REN */
- {WT, dcr, 0xAA}, /* Write pattern to GPIB data lines */
- {RD, bsr, 0x55}, /* Verify DAV, NRFD, SRQ, and REN are set */
- {RD, dsr, 0xAA}, /* Verify data pattern written previously */
- {WT, bcr, 0xAA}, /* Set ATN, NDAC, EOI, & IFC */
- {WT, dcr, 0x55}, /* Write pattern to GPIB data lines */
- {RD, bsr, 0xAA}, /* Verify ATN, NDAC, EOI, & IFC are set */
- {RD, dsr, 0x55}, /* Verify data pattern written previously */
- {WT, bcr, 0x00}, /* Clear control lines */
- {WT, dcr, 0x00}, /* Clear data lines */
- {RD, bsr, 0x00}, /* Verify control lines are clear */
- {RD, dsr, 0x00}, /* Verify data lines are clear */
- {END, 0, 0}
-};
-
-static struct tst tst_adr0_1[] = {
- {WT, adr, 0x55}, /* Set Primary talk address */
- {WT, adr, 0xAA}, /* Set Secondary listen address */
- {RD, adr0, 0x55}, /* Read Primary address */
- {RD, adr1, 0x2A}, /* Read Secondary address */
- {WT, adr, 0x2A}, /* Set Primay listen address */
- {WT, adr, 0xD5}, /* Set Secondary talk address */
- {RD, adr0, 0x2A}, /* Read Primary address */
- {RD, adr1, 0x55}, /* Read Secondary address */
- {END, 0, 0}
-};
-
-static struct tst tst_cdor_dir[] = {
- {WT, admr, 0xF0}, /* program AT-GPIB as talker only and
- * listener only */
- {RD, isr1, 0x02}, /* check DO bit set */
- {RD, adsr, 0x46}, /* check AT-GPIB is both talker active
- * and listener active */
- {WT, cdor, 0xAA}, /* write out data byte */
- {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */
- {RD, isr1, 0x03}, /* check DO and DI bits set */
- {RD, dir, 0xAA}, /* verify data received */
- {WT, cdor, 0x55}, /* write out data byte */
- {xDELAY, 0, 1}, /* One ISA I/O Cycle (500-ns) */
- {RD, dir, 0x55}, /* verify data received */
- {END, 0, 0}
-};
-
-static struct tst tst_spmr_spsr[] = {
- {WT, spsr, 0x00}, /* Write pattern to SPSR register */
- {RD, spmr, 0x00}, /* Read back previously written pattern */
- {WT, spsr, 0xBF}, /* Write pattern to SPSR register */
- {RD, spmr, 0xBF}, /* Read back previously written pattern */
- {END, 0, 0}
-};
-
-static struct tst tst_count0_1[] = {
- {WT, cnt0, 0x55}, /* Verify every other bit can be set */
- {WT, cnt1, 0xAA},
- {RD, cnt0, 0x55}, /* Read back previously written pattern */
- {RD, cnt1, 0xAA},
- {WT, cnt0, 0xAA}, /* Verify every other bit can be set */
- {WT, cnt1, 0x55},
- {RD, cnt0, 0xAA}, /* Read back previously written pattern */
- {RD, cnt1, 0x55},
- {END, 0, 0}
-};
-
-static int
-tst_exec(struct tnt_softc *sc, struct tst *tp, const char *name)
-{
- uint8_t u;
- int step;
-
- for (step = 0; tp->action != END; tp++, step++) {
- switch (tp->action) {
- case WT:
- bus_write_1(sc->res[1], tp->reg, tp->val);
- break;
- case RD:
- u = bus_read_1(sc->res[1], tp->reg);
- if (u != tp->val) {
- printf(
- "Test %s, step %d: reg(%02x) = %02x",
- name, step, tp->reg, u);
- printf( "should have been %02x\n", tp->val);
- return (1);
- }
- break;
- case xDELAY:
- DELAY(tp->val);
- break;
- default:
- printf("Unknown action in test %s, step %d: %d\n",
- name, step, tp->action);
- return (1);
- }
- }
- if (bootverbose)
- printf("Test %s passed\n", name);
- return (0);
-}
-
-static int
-tnt_probe(device_t dev)
-{
-
- if (pci_get_vendor(dev) == 0x1093 && pci_get_device(dev) == 0xc801) {
- device_set_desc(dev, "NI PCI-GPIB");
- return (BUS_PROBE_DEFAULT);
- }
- return (ENXIO);
-}
-
-static int
-tnt_attach(device_t dev)
-{
- struct tnt_softc *sc;
- int error, i;
- uint8_t version;
-
- sc = device_get_softc(dev);
-
- error = bus_alloc_resources(dev, tnt_res_spec, sc->res);
- if (error)
- return (error);
-
- error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
- NULL, upd7210intr, &sc->upd7210, &sc->intr_handler);
-
- /* IO Device Window Base Size Register (IODWBSR) */
- bus_write_4(sc->res[0], 0xc0, rman_get_start(sc->res[1]) | 0x80);
-
- tst_exec(sc, tst_reset, "Reset");
- tst_exec(sc, tst_read_reg, "Read registers");
- tst_exec(sc, tst_bsr_dcr, "BSR & DCR");
- tst_exec(sc, tst_adr0_1, "ADR0,1");
- tst_exec(sc, tst_cdor_dir, "CDOR/DIR");
- tst_exec(sc, tst_spmr_spsr, "CPMR/SPSR");
- tst_exec(sc, tst_count0_1, "COUNT0:1");
- tst_exec(sc, tst_reset, "Reset");
-
- version = bus_read_1(sc->res[1], csr);
- version = (version >> 4) & 0x0f;
- device_printf(dev, "Chip version 0x%02x (TNT%s)\n",
- version,
- version >= 4? "5004 or above": "4882");
- if (version >= 4) {
- device_printf(dev, "Forcing FIFO mode\n");
- sc->upd7210.use_fifo = 1;
- } else {
- sc->upd7210.use_fifo = 0;
- }
-
- /* pass 7210 interrupts through */
- bus_write_1(sc->res[1], imr3, 0x02);
-
- for (i = 0; i < 8; i++) {
- sc->upd7210.reg_res[i] = sc->res[1];
- sc->upd7210.reg_offset[i] = i * 2;
- }
-
- /* No DMA help */
- sc->upd7210.dmachan = -1;
-
- /* No "special interrupt handling" needed here. */
- sc->upd7210.irq_clear_res = NULL;
-
- upd7210attach(&sc->upd7210);
- device_printf(dev, "attached gpib%d\n", sc->upd7210.unit);
-
- if (sc->upd7210.use_fifo)
- bus_write_1(sc->res[0], hssel, 0x01); /* one-chip mode */
-
-
- return (0);
-}
-
-static int
-tnt_detach(device_t dev)
-{
- struct tnt_softc *sc;
-
- sc = device_get_softc(dev);
- bus_teardown_intr(dev, sc->res[2], sc->intr_handler);
- upd7210detach(&sc->upd7210);
-
- bus_release_resources(dev, tnt_res_spec, sc->res);
-
- return (0);
-}
-
-static device_method_t tnt4882_methods[] = {
- DEVMETHOD(device_probe, tnt_probe),
- DEVMETHOD(device_attach, tnt_attach),
- DEVMETHOD(device_detach, tnt_detach),
- { 0, 0 }
-};
-
-static driver_t pci_gpib_driver = {
- "tnt4882",
- tnt4882_methods,
- sizeof(struct tnt_softc)
-};
-
-static devclass_t pci_gpib_devclass;
-
-DRIVER_MODULE(pci_gpib, pci, pci_gpib_driver, pci_gpib_devclass, 0, 0);
diff --git a/sys/dev/ieee488/tnt4882.h b/sys/dev/ieee488/tnt4882.h
deleted file mode 100644
index 221cfd9..0000000
--- a/sys/dev/ieee488/tnt4882.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * Copyright (c) 2010 Joerg Wunsch
- * 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.
- *
- * $FreeBSD$
- */
-
-enum tnt4882reg {
- dir = 0x00,
- cdor = 0x00,
- isr1 = 0x02,
- imr1 = 0x02,
- isr2 = 0x04,
- imr2 = 0x04,
- accwr = 0x05,
- spsr = 0x06,
- spmr = 0x06,
- intr = 0x07,
- adsr = 0x08,
- admr = 0x08,
- cnt2 = 0x09,
- cptr = 0x0a,
- auxmr = 0x0a,
- tauxcr = 0x0a, /* 9914 mode register */
- cnt3 = 0x0b,
- adr0 = 0x0c,
- adr = 0x0c,
- hssel = 0x0d,
- adr1 = 0x0e,
- eosr = 0x0e,
- sts1 = 0x10,
- cfg = 0x10,
- dsr = 0x11,
- sh_cnt = 0x11,
- imr3 = 0x12,
- hier = 0x13,
- cnt0 = 0x14,
- misc = 0x15,
- cnt1 = 0x16,
- csr = 0x17,
- keyreg = 0x17,
- fifob = 0x18,
- fifoa = 0x19,
- isr3 = 0x1a,
- ccr = 0x1a,
- sasr = 0x1b,
- dcr = 0x1b,
- sts2 = 0x1c,
- cmdr = 0x1c,
- isr0 = 0x1d,
- imr0 = 0x1d,
- timer = 0x1e,
- bsr = 0x1f,
- bcr = 0x1f
-};
-
diff --git a/sys/dev/ieee488/ugpib.h b/sys/dev/ieee488/ugpib.h
deleted file mode 100644
index 726a702..0000000
--- a/sys/dev/ieee488/ugpib.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
- * 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.
- *
- * $FreeBSD$
- *
- */
-
-#ifndef _DEV_IEEE488_UGPIB_H_
-#define _DEV_IEEE488_UGPIB_H_
-
-/* ibfoo() return values */
-#define EDVR 0 /* System error */
-#define ECIC 1 /* Not Active Controller */
-#define ENOL 2 /* Nobody listening */
-#define EADR 3 /* Controller not addressed */
-#define EARG 4 /* Invalid argument */
-#define ESAC 5 /* Not System Controller */
-#define EABO 6 /* I/O Aborted/Time out */
-#define ENEB 7 /* No such controller */
-#define EOIP 10 /* Async I/O in progress */
-#define ECAP 11 /* No such capability */
-#define EFSO 12 /* File system error */
-#define EBUS 14 /* Command byte xfer error */
-#define ESTB 15 /* Serial poll status byte lost */
-#define ESRQ 16 /* SRQ line stuck */
-#define ETAB 20 /* Table problem */
-
-/* ibsta bits */
-#define ERR (1<<15) /* Error */
-#define TIMO (1<<14) /* Timeout */
-#define END (1<<13) /* EOI/EOS */
-#define SRQI (1<<12) /* SRQ */
-#define RQS (1<<11) /* Device requests service */
-#define SPOLL (1<<10) /* Serial Poll */
-#define EVENT (1<<9) /* Event occured */
-#define CMPL (1<<8) /* I/O complete */
-#define LOK (1<<7) /* Lockout */
-#define REM (1<<6) /* Remote */
-#define CIC (1<<5) /* CIC */
-#define ATN (1<<4) /* ATN */
-#define TACS (1<<3) /* Talker */
-#define LACS (1<<2) /* Listener */
-#define DTAS (1<<1) /* Device trigger status */
-#define DCAS (1<<0) /* Device clear state */
-
-/* Timeouts */
-#define TNONE 0
-#define T10us 1
-#define T30us 2
-#define T100us 3
-#define T300us 4
-#define T1ms 5
-#define T3ms 6
-#define T10ms 7
-#define T30ms 8
-#define T100ms 9
-#define T300ms 10
-#define T1s 11
-#define T3s 12
-#define T10s 13
-#define T30s 14
-#define T100s 15
-#define T300s 16
-#define T1000s 17
-
-/* EOS bits */
-#define REOS (1 << 10)
-#define XEOS (1 << 11)
-#define BIN (1 << 12)
-
-/* Bus commands */
-#define GTL 0x01 /* Go To Local */
-#define SDC 0x04 /* Selected Device Clear */
-#define GET 0x08 /* Group Execute Trigger */
-#define LAD 0x20 /* Listen address */
-#define UNL 0x3F /* Unlisten */
-#define TAD 0x40 /* Talk address */
-#define UNT 0x5F /* Untalk */
-
-#ifndef _KERNEL
-
-extern int ibcnt, iberr, ibsta;
-
-int ibask(int handle, int option, int *retval);
-int ibbna(int handle, char *bdname);
-int ibcac(int handle, int v);
-int ibclr(int handle);
-int ibcmd(int handle, void *buffer, long cnt);
-int ibcmda(int handle, void *buffer, long cnt);
-int ibconfig(int handle, int option, int value);
-int ibdev(int boardID, int pad, int sad, int tmo, int eot, int eos);
-int ibdiag(int handle, void *buffer, long cnt);
-int ibdma(int handle, int v);
-int ibeos(int handle, int eos);
-int ibeot(int handle, int eot);
-int ibevent(int handle, short *event);
-int ibfind(char *bdname);
-int ibgts(int handle, int v);
-int ibist(int handle, int v);
-int iblines(int handle, short *lines);
-int ibllo(int handle);
-int ibln(int handle, int padval, int sadval, short *listenflag);
-int ibloc(int handle);
-int ibonl(int handle, int v);
-int ibpad(int handle, int pad);
-int ibpct(int handle);
-int ibpoke(int handle, int option, int value);
-int ibppc(int handle, int v);
-int ibrd(int handle, void *buffer, long cnt);
-int ibrda(int handle, void *buffer, long cnt);
-int ibrdf(int handle, char *flname);
-int ibrdkey(int handle, void *buffer, int cnt);
-int ibrpp(int handle, char *ppr);
-int ibrsc(int handle, int v);
-int ibrsp(int handle, char *spr);
-int ibrsv(int handle, int v);
-int ibsad(int handle, int sad);
-int ibsgnl(int handle, int v);
-int ibsic(int handle);
-int ibsre(int handle, int v);
-int ibsrq(void (*func)(void));
-int ibstop(int handle);
-int ibtmo(int handle, int tmo);
-int ibtrap(int mask, int mode);
-int ibtrg(int handle);
-int ibwait(int handle, int mask);
-int ibwrt(int handle, const void *buffer, long cnt);
-int ibwrta(int handle, const void *buffer, long cnt);
-int ibwrtf(int handle, const char *flname);
-int ibwrtkey(int handle, const void *buffer, int cnt);
-int ibxtrc(int handle, void *buffer, long cnt);
-#endif /* _KERNEL */
-#endif /* _DEV_IEEE488_UGPIB_H_ */
diff --git a/sys/dev/ieee488/upd7210.c b/sys/dev/ieee488/upd7210.c
deleted file mode 100644
index 0e76c83..0000000
--- a/sys/dev/ieee488/upd7210.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
- * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
- * 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.
- *
- * High-level driver for µPD7210 based GPIB cards.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-# define GPIB_DEBUG
-# undef GPIB_DEBUG
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/limits.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/bus.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/uio.h>
-#include <sys/time.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <isa/isavar.h>
-
-#define UPD7210_HW_DRIVER
-#define UPD7210_SW_DRIVER
-#include <dev/ieee488/upd7210.h>
-#include <dev/ieee488/tnt4882.h>
-
-static MALLOC_DEFINE(M_GPIB, "GPIB", "GPIB");
-
-/* upd7210 generic stuff */
-
-void
-upd7210_print_isr(u_int isr1, u_int isr2)
-{
- printf("isr1=0x%b isr2=0x%b",
- isr1, "\20\10CPT\7APT\6DET\5ENDRX\4DEC\3ERR\2DO\1DI",
- isr2, "\20\10INT\7SRQI\6LOK\5REM\4CO\3LOKC\2REMC\1ADSC");
-}
-
-u_int
-upd7210_rd(struct upd7210 *u, enum upd7210_rreg reg)
-{
- u_int r;
-
- r = bus_read_1(u->reg_res[reg], u->reg_offset[reg]);
- u->rreg[reg] = r;
- return (r);
-}
-
-void
-upd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val)
-{
-
- bus_write_1(u->reg_res[reg], u->reg_offset[reg], val);
- u->wreg[reg] = val;
- if (reg == AUXMR)
- u->wreg[8 + (val >> 5)] = val & 0x1f;
-}
-
-void
-upd7210intr(void *arg)
-{
- u_int isr_1, isr_2, isr_3;
- struct upd7210 *u;
-
- u = arg;
- mtx_lock(&u->mutex);
- isr_1 = upd7210_rd(u, ISR1);
- isr_2 = upd7210_rd(u, ISR2);
- if (u->use_fifo) {
- isr_3 = bus_read_1(u->reg_res[0], isr3);
- } else {
- isr_3 = 0;
- }
- if (isr_1 != 0 || isr_2 != 0 || isr_3 != 0) {
- if (u->busy == 0 || u->irq == NULL || !u->irq(u, isr_3)) {
-#if 0
- printf("upd7210intr [%02x %02x %02x",
- upd7210_rd(u, DIR), isr1, isr2);
- printf(" %02x %02x %02x %02x %02x] ",
- upd7210_rd(u, SPSR),
- upd7210_rd(u, ADSR),
- upd7210_rd(u, CPTR),
- upd7210_rd(u, ADR0),
- upd7210_rd(u, ADR1));
- upd7210_print_isr(isr1, isr2);
- printf("\n");
-#endif
- }
- /*
- * "special interrupt handling"
- *
- * In order to implement shared IRQs, the original
- * PCIIa uses IO locations 0x2f0 + (IRQ#) as an output
- * location. If an ISR for a particular card has
- * detected this card triggered the IRQ, it must reset
- * the card's IRQ by writing (anything) to that IO
- * location.
- *
- * Some clones apparently don't implement this
- * feature, but National Instrument cards do.
- */
- if (u->irq_clear_res != NULL)
- bus_write_1(u->irq_clear_res, 0, 42);
- }
- mtx_unlock(&u->mutex);
-}
-
-int
-upd7210_take_ctrl_async(struct upd7210 *u)
-{
- int i;
-
- upd7210_wr(u, AUXMR, AUXMR_TCA);
-
- if (!(upd7210_rd(u, ADSR) & ADSR_ATN))
- return (0);
- for (i = 0; i < 20; i++) {
- DELAY(1);
- if (!(upd7210_rd(u, ADSR) & ADSR_ATN))
- return (0);
- }
- return (1);
-}
-
-int
-upd7210_goto_standby(struct upd7210 *u)
-{
- int i;
-
- upd7210_wr(u, AUXMR, AUXMR_GTS);
-
- if (upd7210_rd(u, ADSR) & ADSR_ATN)
- return (0);
- for (i = 0; i < 20; i++) {
- DELAY(1);
- if (upd7210_rd(u, ADSR) & ADSR_ATN)
- return (0);
- }
- return (1);
-}
-
-/* Unaddressed Listen Only mode */
-
-static int
-gpib_l_irq(struct upd7210 *u, int isr_3)
-{
- int i;
- int have_data = 0;
-
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- if (isr_3 & 0x04) {
- /* FIFO not empty */
- i = bus_read_1(u->reg_res[0], fifob);
- have_data = 1;
- bus_write_1(u->reg_res[0], cnt0, -1);
- bus_write_1(u->reg_res[0], cnt1, (-1) >> 8);
- bus_write_1(u->reg_res[0], cnt2, (-1) >> 16);
- bus_write_1(u->reg_res[0], cnt3, (-1) >> 24);
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- }
- } else if (u->rreg[ISR1] & 1) {
- i = upd7210_rd(u, DIR);
- have_data = 1;
- }
-
- if (have_data) {
- u->buf[u->buf_wp++] = i;
- u->buf_wp &= (u->bufsize - 1);
- i = (u->buf_rp + u->bufsize - u->buf_wp) & (u->bufsize - 1);
- if (i < 8) {
- if (u->use_fifo)
- bus_write_1(u->reg_res[0], imr3, 0x00);
- else
- upd7210_wr(u, IMR1, 0);
- }
- wakeup(u->buf);
- return (1);
- }
- return (0);
-}
-
-static int
-gpib_l_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- if (u->busy) {
- mtx_unlock(&u->mutex);
- return (EBUSY);
- }
- u->busy = 1;
- u->irq = gpib_l_irq;
- mtx_unlock(&u->mutex);
-
- u->buf = malloc(PAGE_SIZE, M_GPIB, M_WAITOK);
- u->bufsize = PAGE_SIZE;
- u->buf_wp = 0;
- u->buf_rp = 0;
-
- upd7210_wr(u, AUXMR, AUXMR_CRST); /* chip reset */
- DELAY(10000);
- upd7210_wr(u, AUXMR, C_ICR | 8); /* 8 MHz clock */
- DELAY(1000);
- upd7210_wr(u, ADR, 0x60); /* ADR0: disable listener and talker 0 */
- upd7210_wr(u, ADR, 0xe0); /* ADR1: disable listener and talker 1 */
- upd7210_wr(u, ADMR, 0x70); /* listen-only (lon) */
- upd7210_wr(u, AUXMR, AUXMR_PON); /* immediate execute power-on (pon) */
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- bus_write_1(u->reg_res[0], cmdr, 0x10); /* reset FIFO */
- bus_write_1(u->reg_res[0], cfg, 0x20); /* xfer IN, 8-bit FIFO */
- bus_write_1(u->reg_res[0], cnt0, -1);
- bus_write_1(u->reg_res[0], cnt1, (-1) >> 8);
- bus_write_1(u->reg_res[0], cnt2, (-1) >> 16);
- bus_write_1(u->reg_res[0], cnt3, (-1) >> 24);
- bus_write_1(u->reg_res[0], cmdr, 0x04); /* GO */
- bus_write_1(u->reg_res[0], imr3, 0x04); /* NEF IE */
- } else {
- /* µPD7210/NAT7210, or TNT4882 in non-FIFO mode */
- upd7210_wr(u, IMR1, 0x01); /* data in interrupt enable */
- }
- return (0);
-}
-
-static int
-gpib_l_close(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
- struct upd7210 *u;
-
- u = dev->si_drv1;
-
- mtx_lock(&u->mutex);
- u->busy = 0;
- if (u->use_fifo) {
- /* TNT5004 or TNT4882 in FIFO mode */
- bus_write_1(u->reg_res[0], cmdr, 0x22); /* soft RESET */
- bus_write_1(u->reg_res[0], imr3, 0x00);
- }
- upd7210_wr(u, AUXMR, AUXMR_CRST);
- DELAY(10000);
- upd7210_wr(u, IMR1, 0x00);
- upd7210_wr(u, IMR2, 0x00);
- free(u->buf, M_GPIB);
- u->buf = NULL;
- mtx_unlock(&u->mutex);
- return (0);
-}
-
-static int
-gpib_l_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
- struct upd7210 *u;
- int error;
- size_t z;
-
- u = dev->si_drv1;
- error = 0;
-
- mtx_lock(&u->mutex);
- while (u->buf_wp == u->buf_rp) {
- error = msleep(u->buf, &u->mutex, PZERO | PCATCH,
- "gpibrd", hz);
- if (error && error != EWOULDBLOCK) {
- mtx_unlock(&u->mutex);
- return (error);
- }
- }
- while (uio->uio_resid > 0 && u->buf_wp != u->buf_rp) {
- if (u->buf_wp < u->buf_rp)
- z = u->bufsize - u->buf_rp;
- else
- z = u->buf_wp - u->buf_rp;
- if (z > uio->uio_resid)
- z = uio->uio_resid;
- mtx_unlock(&u->mutex);
- error = uiomove(u->buf + u->buf_rp, z, uio);
- mtx_lock(&u->mutex);
- if (error)
- break;
- u->buf_rp += z;
- u->buf_rp &= (u->bufsize - 1);
- }
- if (u->use_fifo) {
- bus_write_1(u->reg_res[0], imr3, 0x04); /* NFF IE */
- } else {
- if (u->wreg[IMR1] == 0)
- upd7210_wr(u, IMR1, 0x01);
- }
- mtx_unlock(&u->mutex);
- return (error);
-}
-
-static struct cdevsw gpib_l_cdevsw = {
- .d_version = D_VERSION,
- .d_name = "gpib_l",
- .d_open = gpib_l_open,
- .d_close = gpib_l_close,
- .d_read = gpib_l_read,
-};
-
-/* Housekeeping */
-
-static struct unrhdr *units;
-
-void
-upd7210attach(struct upd7210 *u)
-{
- struct cdev *dev;
-
- if (units == NULL)
- units = new_unrhdr(0, INT_MAX, NULL);
- u->unit = alloc_unr(units);
- mtx_init(&u->mutex, "gpib", NULL, MTX_DEF);
- u->cdev = make_dev(&gpib_l_cdevsw, u->unit,
- UID_ROOT, GID_WHEEL, 0444,
- "gpib%ul", u->unit);
- u->cdev->si_drv1 = u;
-
- dev = make_dev(&gpib_ib_cdevsw, u->unit,
- UID_ROOT, GID_WHEEL, 0444,
- "gpib%uib", u->unit);
- dev->si_drv1 = u;
- dev_depends(u->cdev, dev);
-}
-
-void
-upd7210detach(struct upd7210 *u)
-{
-
- destroy_dev(u->cdev);
- mtx_destroy(&u->mutex);
- free_unr(units, u->unit);
-}
diff --git a/sys/dev/ieee488/upd7210.h b/sys/dev/ieee488/upd7210.h
deleted file mode 100644
index 27e3a7a..0000000
--- a/sys/dev/ieee488/upd7210.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*-
- * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
- * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
- * 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.
- *
- * $FreeBSD$
- *
- * Locating an actual µPD7210 data book has proven quite impossible for me.
- * There are a fair number of newer chips which are supersets of the µPD7210
- * but they are particular eager to comprehensively mark what the extensions
- * are and what is in the base set. Some even give the registers and their
- * bits new names.
- *
- * The following information is based on a description of the µPD7210 found
- * in an old manual for a VME board which used the chip.
- */
-
-#ifndef _DEV_IEEE488_UPD7210_H_
-#define _DEV_IEEE488_UPD7210_H_
-#ifdef _KERNEL
-
-struct upd7210;
-struct ibfoo;
-
-/* upd7210 interface definitions for HW drivers */
-
-typedef int upd7210_irq_t(struct upd7210 *, int);
-
-struct upd7210 {
- struct resource *reg_res[8];
- struct resource *irq_clear_res;
- u_int reg_offset[8];
- int dmachan;
- int unit;
- int use_fifo;
-
- /* private stuff */
- struct mtx mutex;
- uint8_t rreg[8];
- uint8_t wreg[8 + 8];
-
- upd7210_irq_t *irq;
-
- int busy;
- u_char *buf;
- size_t bufsize;
- u_int buf_wp;
- u_int buf_rp;
- struct cdev *cdev;
-
- struct ibfoo *ibfoo;
-};
-
-#ifdef UPD7210_HW_DRIVER
-void upd7210intr(void *);
-void upd7210attach(struct upd7210 *);
-void upd7210detach(struct upd7210 *);
-#endif
-
-#ifdef UPD7210_SW_DRIVER
-
-/* upd7210 hardware definitions. */
-
-/* Write registers */
-enum upd7210_wreg {
- CDOR = 0, /* Command/Data Out Register */
- IMR1 = 1, /* Interrupt Mask Register 1 */
- IMR2 = 2, /* Interrupt Mask Register 2 */
- SPMR = 3, /* Serial Poll Mode Register */
- ADMR = 4, /* ADdress Mode Register */
- AUXMR = 5, /* AUXilliary Mode Register */
- ICR = 5, /* Internal Counter Register */
- PPR = 5, /* Parallel Poll Register */
- AUXRA = 5, /* AUXilliary Register A */
- AUXRB = 5, /* AUXilliary Register B */
- AUXRE = 5, /* AUXilliary Register E */
- ADR = 6, /* ADdress Register */
- EOSR = 7, /* End-Of-String Register */
-};
-
-/* Read registers */
-enum upd7210_rreg {
- DIR = 0, /* Data In Register */
- ISR1 = 1, /* Interrupt Status Register 1 */
- ISR2 = 2, /* Interrupt Status Register 2 */
- SPSR = 3, /* Serial Poll Status Register */
- ADSR = 4, /* ADdress Status Register */
- CPTR = 5, /* Command Pass Though Register */
- ADR0 = 6, /* ADdress Register 0 */
- ADR1 = 7, /* ADdress Register 1 */
-};
-
-/* Bits for ISR1 and IMR1 */
-#define IXR1_DI (1 << 0) /* Data In */
-#define IXR1_DO (1 << 1) /* Data Out */
-#define IXR1_ERR (1 << 2) /* Error */
-#define IXR1_DEC (1 << 3) /* Device Clear */
-#define IXR1_ENDRX (1 << 4) /* End Received */
-#define IXR1_DET (1 << 5) /* Device Execute Trigger */
-#define IXR1_APT (1 << 6) /* Address Pass-Through */
-#define IXR1_CPT (1 << 7) /* Command Pass-Through */
-
-/* Bits for ISR2 and IMR2 */
-#define IXR2_ADSC (1 << 0) /* Addressed Status Change */
-#define IXR2_REMC (1 << 1) /* Remote Change */
-#define IXR2_LOKC (1 << 2) /* Lockout Change */
-#define IXR2_CO (1 << 3) /* Command Out */
-#define ISR2_REM (1 << 4) /* Remove */
-#define IMR2_DMAI (1 << 4) /* DMA In Enable */
-#define ISR2_LOK (1 << 5) /* Lockout */
-#define IMR2_DMAO (1 << 5) /* DMA Out Enable */
-#define IXR2_SRQI (1 << 6) /* Service Request Input */
-#define ISR2_INT (1 << 7) /* Interrupt */
-
-#define SPSR_PEND (1 << 6) /* Pending */
-#define SPMR_RSV (1 << 6) /* Request SerVice */
-
-#define ADSR_MJMN (1 << 0) /* MaJor MiNor */
-#define ADSR_TA (1 << 1) /* Talker Active */
-#define ADSR_LA (1 << 2) /* Listener Active */
-#define ADSR_TPAS (1 << 3) /* Talker Primary Addr. State */
-#define ADSR_LPAS (1 << 4) /* Listener Primary Addr. State */
-#define ADSR_SPMS (1 << 5) /* Serial Poll Mode State */
-#define ADSR_ATN (1 << 6) /* Attention */
-#define ADSR_CIC (1 << 7) /* Controller In Charge */
-
-#define ADMR_ADM0 (1 << 0) /* Address Mode 0 */
-#define ADMR_ADM1 (1 << 1) /* Address Mode 1 */
-#define ADMR_TRM0 (1 << 4) /* Transmit/Receive Mode 0 */
-#define ADMR_TRM1 (1 << 5) /* Transmit/Receive Mode 1 */
-#define ADMR_LON (1 << 6) /* Listen Only */
-#define ADMR_TON (1 << 7) /* Talk Only */
-
-/* Constant part of overloaded write registers */
-#define C_ICR 0x20
-#define C_PPR 0x60
-#define C_AUXA 0x80
-#define C_AUXB 0xa0
-#define C_AUXE 0xc0
-
-#define AUXMR_PON 0x00 /* Immediate Execute pon */
-#define AUXMR_CPP 0x01 /* Clear Parallel Poll */
-#define AUXMR_CRST 0x02 /* Chip Reset */
-#define AUXMR_RFD 0x03 /* Finish Handshake */
-#define AUXMR_TRIG 0x04 /* Trigger */
-#define AUXMR_RTL 0x05 /* Return to local */
-#define AUXMR_SEOI 0x06 /* Send EOI */
-#define AUXMR_NVSA 0x07 /* Non-Valid Secondary cmd/addr */
- /* 0x08 undefined/unknown */
-#define AUXMR_SPP 0x09 /* Set Parallel Poll */
- /* 0x0a undefined/unknown */
- /* 0x0b undefined/unknown */
- /* 0x0c undefined/unknown */
- /* 0x0d undefined/unknown */
- /* 0x0e undefined/unknown */
-#define AUXMR_VSA 0x0f /* Valid Secondary cmd/addr */
-#define AUXMR_GTS 0x10 /* Go to Standby */
-#define AUXMR_TCA 0x11 /* Take Control Async (pulsed) */
-#define AUXMR_TCS 0x12 /* Take Control Synchronously */
-#define AUXMR_LISTEN 0x13 /* Listen */
-#define AUXMR_DSC 0x14 /* Disable System Control */
- /* 0x15 undefined/unknown */
-#define AUXMR_SIFC 0x16 /* Set IFC */
-#define AUXMR_CREN 0x17 /* Clear REN */
- /* 0x18 undefined/unknown */
- /* 0x19 undefined/unknown */
-#define AUXMR_TCSE 0x1a /* Take Control Sync on End */
-#define AUXMR_LCM 0x1b /* Listen Continuously Mode */
-#define AUXMR_LUNL 0x1c /* Local Unlisten */
-#define AUXMR_EPP 0x1d /* Execute Parallel Poll */
-#define AUXMR_CIFC 0x1e /* Clear IFC */
-#define AUXMR_SREN 0x1f /* Set REN */
-
-#define PPR_U (1 << 4) /* Unconfigure */
-#define PPR_S (1 << 3) /* Status Polarity */
-
-#define AUXA_HLDA (1 << 0) /* Holdoff on All */
-#define AUXA_HLDE (1 << 1) /* Holdoff on END */
-#define AUXA_REOS (1 << 2) /* End on EOS received */
-#define AUXA_XEOS (1 << 3) /* Transmit END with EOS */
-#define AUXA_BIN (1 << 4) /* Binary */
-
-#define AUXB_CPTE (1 << 0) /* Cmd Pass Through Enable */
-#define AUXB_SPEOI (1 << 1) /* Send Serial Poll EOI */
-#define AUXB_TRI (1 << 2) /* Three-State Timing */
-#define AUXB_INV (1 << 3) /* Invert */
-#define AUXB_ISS (1 << 4) /* Individual Status Select */
-
-#define AUXE_DHDT (1 << 0) /* DAC Holdoff on DTAS */
-#define AUXE_DHDC (1 << 1) /* DAC Holdoff on DCAS */
-
-#define ADR0_DL0 (1 << 5) /* Disable Listener 0 */
-#define ADR0_DT0 (1 << 6) /* Disable Talker 0 */
-
-#define ADR_DL (1 << 5) /* Disable Listener */
-#define ADR_DT (1 << 6) /* Disable Talker */
-#define ADR_ARS (1 << 7) /* Address Register Select */
-
-#define ADR1_DL1 (1 << 5) /* Disable Listener 1 */
-#define ADR1_DT1 (1 << 6) /* Disable Talker 1 */
-#define ADR1_EOI (1 << 7) /* End or Identify */
-
-/* Stuff from software drivers */
-extern struct cdevsw gpib_ib_cdevsw;
-
-/* Stuff from upd7210.c */
-void upd7210_print_isr(u_int isr1, u_int isr2);
-u_int upd7210_rd(struct upd7210 *u, enum upd7210_rreg reg);
-void upd7210_wr(struct upd7210 *u, enum upd7210_wreg reg, u_int val);
-int upd7210_take_ctrl_async(struct upd7210 *u);
-int upd7210_goto_standby(struct upd7210 *u);
-
-#endif /* UPD7210_SW_DRIVER */
-
-#endif /* _KERNEL */
-#endif /* _DEV_IEEE488_UPD7210_H_ */
diff --git a/sys/dev/ipmi/ipmi_kcs.c b/sys/dev/ipmi/ipmi_kcs.c
index 76adf8c..eb5884a 100644
--- a/sys/dev/ipmi/ipmi_kcs.c
+++ b/sys/dev/ipmi/ipmi_kcs.c
@@ -184,6 +184,8 @@ kcs_start_write(struct ipmi_softc *sc)
for (retry = 0; retry < 10; retry++) {
/* Wait for IBF = 0 */
status = kcs_wait_for_ibf(sc, 0);
+ if (status & KCS_STATUS_IBF)
+ return (0);
/* Clear OBF */
kcs_clear_obf(sc, status);
@@ -193,6 +195,9 @@ kcs_start_write(struct ipmi_softc *sc)
/* Wait for IBF = 0 */
status = kcs_wait_for_ibf(sc, 0);
+ if (status & KCS_STATUS_IBF)
+ return (0);
+
if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE)
break;
DELAY(1000000);
@@ -222,6 +227,8 @@ kcs_write_byte(struct ipmi_softc *sc, u_char data)
/* Wait for IBF = 0 */
status = kcs_wait_for_ibf(sc, 0);
+ if (status & KCS_STATUS_IBF)
+ return (0);
if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
return (0);
@@ -244,6 +251,8 @@ kcs_write_last_byte(struct ipmi_softc *sc, u_char data)
/* Wait for IBF = 0 */
status = kcs_wait_for_ibf(sc, 0);
+ if (status & KCS_STATUS_IBF)
+ return (0);
if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE)
/* error state */
@@ -274,6 +283,8 @@ kcs_read_byte(struct ipmi_softc *sc, u_char *data)
/* Wait for OBF = 1 */
status = kcs_wait_for_obf(sc, 1);
+ if ((status & KCS_STATUS_OBF) == 0)
+ return (0);
/* Read Data_out */
*data = INB(sc, KCS_DATA);
@@ -288,6 +299,8 @@ kcs_read_byte(struct ipmi_softc *sc, u_char *data)
/* Wait for OBF = 1*/
status = kcs_wait_for_obf(sc, 1);
+ if ((status & KCS_STATUS_OBF) == 0)
+ return (0);
/* Read Dummy */
dummy = INB(sc, KCS_DATA);
diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c
index f3ff082..b0f4285 100644
--- a/sys/dev/isci/isci_controller.c
+++ b/sys/dev/isci/isci_controller.c
@@ -373,6 +373,8 @@ SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller)
fail_on_timeout = 1;
TUNABLE_INT_FETCH("hw.isci.fail_on_task_timeout", &fail_on_timeout);
+ controller->fail_on_task_timeout = fail_on_timeout;
+
/* Attach to CAM using xpt_bus_register now, then immediately freeze
* the simq. It will get released later when initial domain discovery
* is complete.
diff --git a/sys/dev/isci/isci_sysctl.c b/sys/dev/isci/isci_sysctl.c
index 62a10b9..a7c56c6 100644
--- a/sys/dev/isci/isci_sysctl.c
+++ b/sys/dev/isci/isci_sysctl.c
@@ -226,12 +226,13 @@ static int
isci_sysctl_fail_on_task_timeout(SYSCTL_HANDLER_ARGS)
{
struct isci_softc *isci = (struct isci_softc *)arg1;
- int32_t fail_on_timeout = 0;
+ int32_t fail_on_timeout;
int error, i;
+ fail_on_timeout = isci->controllers[0].fail_on_task_timeout;
error = sysctl_handle_int(oidp, &fail_on_timeout, 0, req);
- if (error || fail_on_timeout == 0)
+ if (error || req->newptr == NULL)
return (error);
for (i = 0; i < isci->controller_count; i++)
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index f9edc82..0d762aa 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -2157,6 +2157,10 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length);
len = is->is_first_burst_length;
}
+ if (len > is->is_max_data_segment_length) {
+ ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_max_data_segment_length);
+ len = is->is_max_data_segment_length;
+ }
error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
if (error != 0) {
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index bf8c98d..b287c6c 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -279,7 +279,6 @@ static int iwn_send_btcoex(struct iwn_softc *);
static int iwn_send_advanced_btcoex(struct iwn_softc *);
static int iwn5000_runtime_calib(struct iwn_softc *);
static int iwn_config(struct iwn_softc *);
-static uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
static int iwn_scan(struct iwn_softc *, struct ieee80211vap *,
struct ieee80211_scan_state *, struct ieee80211_channel *);
static int iwn_auth(struct iwn_softc *, struct ieee80211vap *vap);
@@ -6527,18 +6526,6 @@ iwn_config(struct iwn_softc *sc)
return 0;
}
-/*
- * Add an ssid element to a frame.
- */
-static uint8_t *
-ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len)
-{
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = len;
- memcpy(frm, ssid, len);
- return frm + len;
-}
-
static uint16_t
iwn_get_active_dwell_time(struct iwn_softc *sc,
struct ieee80211_channel *c, uint8_t n_probes)
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index a3b9744..ec4d358 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/sysctl.h>
+#include <sys/time.h>
#include <dev/mmc/mmcreg.h>
#include <dev/mmc/mmcbrvar.h>
@@ -76,8 +77,13 @@ struct mmc_softc {
struct intr_config_hook config_intrhook;
device_t owner;
uint32_t last_rca;
+ int squelched; /* suppress reporting of (expected) errors */
+ int log_count;
+ struct timeval log_time;
};
+#define LOG_PPS 5 /* Log no more than 5 errors per second. */
+
/*
* Per-card data
*/
@@ -426,6 +432,13 @@ mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries)
err = cmd->error;
} while (err != MMC_ERR_NONE && retries-- > 0);
+ if (err != MMC_ERR_NONE && sc->squelched == 0) {
+ if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
+ device_printf(sc->dev, "CMD%d failed, RESULT: %d\n",
+ cmd->opcode, err);
+ }
+ }
+
return (err);
}
@@ -436,6 +449,8 @@ mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca,
struct mmc_command appcmd;
int err;
+ /* Squelch error reporting at lower levels, we report below. */
+ sc->squelched++;
do {
memset(&appcmd, 0, sizeof(appcmd));
appcmd.opcode = MMC_APP_CMD;
@@ -455,6 +470,14 @@ mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca,
err = cmd->error;
}
} while (err != MMC_ERR_NONE && retries-- > 0);
+ sc->squelched--;
+
+ if (err != MMC_ERR_NONE && sc->squelched == 0) {
+ if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
+ device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n",
+ cmd->opcode, err);
+ }
+ }
return (err);
}
@@ -760,6 +783,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
mmcbr_set_bus_width(sc->dev, bus_width_8);
mmcbr_update_ios(sc->dev);
+ sc->squelched++; /* Errors are expected, squelch reporting. */
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_W;
@@ -783,6 +807,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.len = 8;
data.flags = MMC_DATA_READ;
err = mmc_wait_for_cmd(sc, &cmd, 0);
+ sc->squelched--;
mmcbr_set_bus_width(sc->dev, bus_width_1);
mmcbr_update_ios(sc->dev);
@@ -795,6 +820,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
mmcbr_set_bus_width(sc->dev, bus_width_4);
mmcbr_update_ios(sc->dev);
+ sc->squelched++; /* Errors are expected, squelch reporting. */
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_W;
@@ -818,6 +844,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.len = 4;
data.flags = MMC_DATA_READ;
err = mmc_wait_for_cmd(sc, &cmd, 0);
+ sc->squelched--;
mmcbr_set_bus_width(sc->dev, bus_width_1);
mmcbr_update_ios(sc->dev);
@@ -1270,7 +1297,9 @@ mmc_discover_cards(struct mmc_softc *sc)
if (bootverbose || mmc_debug)
device_printf(sc->dev, "Probing cards\n");
while (1) {
+ sc->squelched++; /* Errors are expected, squelch reporting. */
err = mmc_all_send_cid(sc, raw_cid);
+ sc->squelched--;
if (err == MMC_ERR_TIMEOUT)
break;
if (err != MMC_ERR_NONE) {
@@ -1417,10 +1446,10 @@ mmc_discover_cards(struct mmc_softc *sc)
break;
}
+ mmc_select_card(sc, ivar->rca);
+
/* Only MMC >= 4.x cards support EXT_CSD. */
if (ivar->csd.spec_vers >= 4) {
- /* Card must be selected to fetch EXT_CSD. */
- mmc_select_card(sc, ivar->rca);
mmc_send_ext_csd(sc, ivar->raw_ext_csd);
/* Handle extended capacity from EXT_CSD */
sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
@@ -1450,7 +1479,6 @@ mmc_discover_cards(struct mmc_softc *sc)
mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_ERASE_GRP_DEF, 1);
}
- mmc_select_card(sc, 0);
} else {
ivar->bus_width = bus_width_1;
ivar->timing = bus_timing_normal;
@@ -1477,6 +1505,7 @@ mmc_discover_cards(struct mmc_softc *sc)
child = device_add_child(sc->dev, NULL, -1);
device_set_ivars(child, ivar);
}
+ mmc_select_card(sc, 0);
}
}
@@ -1536,6 +1565,7 @@ mmc_go_discovery(struct mmc_softc *sc)
/*
* First, try SD modes
*/
+ sc->squelched++; /* Errors are expected, squelch reporting. */
mmcbr_set_mode(dev, mode_sd);
mmc_power_up(sc);
mmcbr_set_bus_mode(dev, pushpull);
@@ -1561,6 +1591,7 @@ mmc_go_discovery(struct mmc_softc *sc)
"MMC probe: OK (OCR: 0x%08x)\n", ocr);
} else if (bootverbose || mmc_debug)
device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr);
+ sc->squelched--;
mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr));
if (mmcbr_get_ocr(dev) != 0)
diff --git a/sys/dev/ofw/ofw_cpu.c b/sys/dev/ofw/ofw_cpu.c
index 2265140..1d01b63 100644
--- a/sys/dev/ofw/ofw_cpu.c
+++ b/sys/dev/ofw/ofw_cpu.c
@@ -171,7 +171,7 @@ ofw_cpu_probe(device_t dev)
{
const char *type = ofw_bus_get_type(dev);
- if (strcmp(type, "cpu") != 0)
+ if (type == NULL || strcmp(type, "cpu") != 0)
return (ENXIO);
device_set_desc(dev, "Open Firmware CPU");
@@ -182,12 +182,20 @@ static int
ofw_cpu_attach(device_t dev)
{
struct ofw_cpu_softc *sc;
+ phandle_t node;
uint32_t cell;
sc = device_get_softc(dev);
- OF_getprop(ofw_bus_get_node(dev), "reg", &cell, sizeof(cell));
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "reg", &cell, sizeof(cell)) < 0) {
+ cell = device_get_unit(dev);
+ device_printf(dev, "missing 'reg' property, using %u\n", cell);
+ }
sc->sc_cpu_pcpu = pcpu_find(cell);
- OF_getprop(ofw_bus_get_node(dev), "clock-frequency", &cell, sizeof(cell));
+ if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) < 0) {
+ device_printf(dev, "missing 'clock-frequency' property\n");
+ return (ENXIO);
+ }
sc->sc_nominal_mhz = cell / 1000000; /* convert to MHz */
bus_generic_probe(dev);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index d2ac111..8f87851 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -268,7 +268,7 @@ static const struct pci_quirk pci_quirks[] = {
{ 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 },
/*
- * Atheros AR8161/AR8162/E2200 ethernet controller has a bug that
+ * Atheros AR8161/AR8162/E2200 Ethernet controllers have a bug that
* MSI interrupt does not assert if PCIM_CMD_INTxDIS bit of the
* command register is set.
*/
@@ -276,6 +276,17 @@ static const struct pci_quirk pci_quirks[] = {
{ 0xE0911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
{ 0x10901969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ /*
+ * Broadcom BCM5714(S)/BCM5715(S)/BCM5780(S) Ethernet MACs don't
+ * issue MSI interrupts with PCIM_CMD_INTxDIS set either.
+ */
+ { 0x166814e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5714 */
+ { 0x166914e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5714S */
+ { 0x166a14e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5780 */
+ { 0x166b14e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5780S */
+ { 0x167814e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5715 */
+ { 0x167914e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5715S */
+
{ 0 }
};
@@ -3866,14 +3877,16 @@ pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
mte->mte_handlers++;
}
- if (!pci_has_quirk(pci_get_devid(dev),
- PCI_QUIRK_MSI_INTX_BUG)) {
- /*
- * Make sure that INTx is disabled if we are
- * using MSI/MSIX
- */
+ /*
+ * Make sure that INTx is disabled if we are using MSI/MSI-X,
+ * unless the device is affected by PCI_QUIRK_MSI_INTX_BUG,
+ * in which case we "enable" INTx so MSI/MSI-X actually works.
+ */
+ if (!pci_has_quirk(pci_get_devid(child),
+ PCI_QUIRK_MSI_INTX_BUG))
pci_set_command_bit(dev, child, PCIM_CMD_INTxDIS);
- }
+ else
+ pci_clear_command_bit(dev, child, PCIM_CMD_INTxDIS);
bad:
if (error) {
(void)bus_generic_teardown_intr(dev, child, irq,
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
index f92d42b..98861ab6 100644
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -149,7 +149,6 @@ static void
sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
{
int timeout;
- uint8_t res;
if (slot->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
if (!(RD4(slot, SDHCI_PRESENT_STATE) &
@@ -168,26 +167,43 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
sdhci_set_clock(slot, clock);
}
- WR1(slot, SDHCI_SOFTWARE_RESET, mask);
-
if (mask & SDHCI_RESET_ALL) {
slot->clock = 0;
slot->power = 0;
}
+ WR1(slot, SDHCI_SOFTWARE_RESET, mask);
+
+ if (slot->quirks & SDHCI_QUIRK_WAITFOR_RESET_ASSERTED) {
+ /*
+ * Resets on TI OMAPs and AM335x are incompatible with SDHCI
+ * specification. The reset bit has internal propagation delay,
+ * so a fast read after write returns 0 even if reset process is
+ * in progress. The workaround is to poll for 1 before polling
+ * for 0. In the worst case, if we miss seeing it asserted the
+ * time we spent waiting is enough to ensure the reset finishes.
+ */
+ timeout = 10000;
+ while ((RD1(slot, SDHCI_SOFTWARE_RESET) & mask) != mask) {
+ if (timeout <= 0)
+ break;
+ timeout--;
+ DELAY(1);
+ }
+ }
+
/* Wait max 100 ms */
- timeout = 100;
+ timeout = 10000;
/* Controller clears the bits when it's done */
- while ((res = RD1(slot, SDHCI_SOFTWARE_RESET)) & mask) {
- if (timeout == 0) {
- slot_printf(slot,
- "Reset 0x%x never completed - 0x%x.\n",
- (int)mask, (int)res);
+ while (RD1(slot, SDHCI_SOFTWARE_RESET) & mask) {
+ if (timeout <= 0) {
+ slot_printf(slot, "Reset 0x%x never completed.\n",
+ mask);
sdhci_dumpregs(slot);
return;
}
timeout--;
- DELAY(1000);
+ DELAY(10);
}
}
@@ -713,9 +729,13 @@ sdhci_timeout(void *arg)
struct sdhci_slot *slot = arg;
if (slot->curcmd != NULL) {
+ slot_printf(slot, " Controller timeout\n");
+ sdhci_dumpregs(slot);
sdhci_reset(slot, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
slot->curcmd->error = MMC_ERR_TIMEOUT;
sdhci_req_done(slot);
+ } else {
+ slot_printf(slot, " Spurious timeout - no active command\n");
}
}
@@ -1274,7 +1294,9 @@ sdhci_generic_intr(struct sdhci_slot *slot)
/* Handle data interrupts. */
if (intmask & SDHCI_INT_DATA_MASK) {
WR4(slot, SDHCI_INT_STATUS, intmask & SDHCI_INT_DATA_MASK);
- sdhci_data_irq(slot, intmask & SDHCI_INT_DATA_MASK);
+ /* Dont call data_irq in case of errored command */
+ if ((intmask & SDHCI_INT_CMD_ERROR_MASK) == 0)
+ sdhci_data_irq(slot, intmask & SDHCI_INT_DATA_MASK);
}
/* Handle AutoCMD12 error interrupt. */
if (intmask & SDHCI_INT_ACMD12ERR) {
diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h
index 5cde2b0..ff1576e 100644
--- a/sys/dev/sdhci/sdhci.h
+++ b/sys/dev/sdhci/sdhci.h
@@ -59,6 +59,8 @@
#define SDHCI_QUIRK_MISSING_CAPS (1<<12)
/* Hardware shifts the 136-bit response, don't do it in software. */
#define SDHCI_QUIRK_DONT_SHIFT_RESPONSE (1<<13)
+/* Wait to see reset bit asserted before waiting for de-asserted */
+#define SDHCI_QUIRK_WAITFOR_RESET_ASSERTED (1<<14)
/*
* Controller registers
@@ -182,8 +184,11 @@
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
-#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
+#define SDHCI_INT_CMD_ERROR_MASK (SDHCI_INT_TIMEOUT | \
SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
+
+#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_CMD_ERROR_MASK)
+
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index 1799d47..6b2f6b8 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -449,6 +449,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(WESTERN, MYPASSPORT_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(WESTERN, MYPASSPORT_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(WESTERN, MYPASSPORT_10, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+ USB_QUIRK(WESTERN, MYPASSPORT_11, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(WESTERN, MYPASSPORTES_00, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(WESTERN, MYPASSPORTES_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(WESTERN, MYPASSPORTES_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 2d86d1b..b9ea927 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -2411,6 +2411,8 @@ product INTEL EASYPC_CAMERA 0x0110 Easy PC Camera
product INTEL TESTBOARD 0x9890 82930 test board
product INTEL2 IRMH 0x0020 Integrated Rate Matching Hub
product INTEL2 IRMH2 0x0024 Integrated Rate Matching Hub
+product INTEL2 IRMH3 0x8000 Integrated Rate Matching Hub
+product INTEL2 IRMH4 0x8008 Integrated Rate Matching Hub
/* Interbiometric products */
product INTERBIOMETRICS IOBOARD 0x1002 FTDI compatible adapter
@@ -4492,6 +4494,7 @@ product WESTERN EXTHDD 0x0400 External HDD
product WESTERN HUB 0x0500 USB HUB
product WESTERN MYBOOK 0x0901 MyBook External HDD
product WESTERN MYPASSPORT_00 0x0704 MyPassport External HDD
+product WESTERN MYPASSPORT_11 0x0741 MyPassport External HDD
product WESTERN MYPASSPORT_01 0x0746 MyPassport External HDD
product WESTERN MYPASSPORT_02 0x0748 MyPassport External HDD
product WESTERN MYPASSPORT_03 0x074A MyPassport External HDD
diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c
index 05b2d79..7695547 100644
--- a/sys/dev/vt/hw/efifb/efifb.c
+++ b/sys/dev/vt/hw/efifb/efifb.c
@@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/fbio.h>
#include <sys/linker.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/rman.h>
#include "opt_platform.h"
@@ -179,3 +182,53 @@ vt_efifb_remap(void *xinfo)
info->fb_size, VM_MEMATTR_WRITE_COMBINING);
}
+/* Dummy NewBus functions to reserve the resources used by the efifb driver */
+static void
+vtefifb_identify(driver_t *driver, device_t parent)
+{
+
+ if (local_info.fb_pbase == 0 || local_info.fb_size == 0)
+ return;
+
+ if (BUS_ADD_CHILD(parent, 0, driver->name, 0) == NULL)
+ panic("Unable to attach vt_efifb console");
+}
+
+static int
+vtefifb_probe(device_t dev)
+{
+
+ device_set_desc(dev, "vt_efifb driver");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+vtefifb_attach(device_t dev)
+{
+ struct resource *pseudo_phys_res;
+ int res_id;
+
+ res_id = 0;
+ pseudo_phys_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &res_id, local_info.fb_pbase,
+ local_info.fb_pbase + local_info.fb_size,
+ local_info.fb_size, RF_ACTIVE);
+ if (pseudo_phys_res == NULL)
+ panic("Unable to reserve vt_efifb memory");
+ return (0);
+}
+
+/*-------------------- Private Device Attachment Data -----------------------*/
+static device_method_t vtefifb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, vtefifb_identify),
+ DEVMETHOD(device_probe, vtefifb_probe),
+ DEVMETHOD(device_attach, vtefifb_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(vtefifb, vtefifb_driver, vtefifb_methods, 0);
+devclass_t vtefifb_devclass;
+
+DRIVER_MODULE(vtefifb, nexus, vtefifb_driver, vtefifb_devclass, NULL, NULL);
diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index abddbf5..7f35053 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/rman.h>
#include <dev/vt/vt.h>
#include <dev/vt/hw/vga/vt_vga_reg.h>
@@ -56,6 +59,7 @@ struct vga_softc {
bus_space_handle_t vga_reg_handle;
int vga_wmode;
term_color_t vga_curfg, vga_curbg;
+ boolean_t vga_enabled;
};
/* Convenience macros. */
@@ -1228,6 +1232,7 @@ vga_init(struct vt_device *vd)
vd->vd_height = VT_VGA_HEIGHT;
}
vga_initialize(vd, textmode);
+ sc->vga_enabled = true;
return (CN_INTERNAL);
}
@@ -1241,3 +1246,53 @@ vga_postswitch(struct vt_device *vd)
/* Ask vt(9) to update chars on visible area. */
vd->vd_flags |= VDF_INVALID;
}
+
+/* Dummy NewBus functions to reserve the resources used by the vt_vga driver */
+static void
+vtvga_identify(driver_t *driver, device_t parent)
+{
+
+ if (!vga_conssoftc.vga_enabled)
+ return;
+
+ if (BUS_ADD_CHILD(parent, 0, driver->name, 0) == NULL)
+ panic("Unable to attach vt_vga console");
+}
+
+static int
+vtvga_probe(device_t dev)
+{
+
+ device_set_desc(dev, "vt_vga driver");
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+vtvga_attach(device_t dev)
+{
+ struct resource *pseudo_phys_res;
+ int res_id;
+
+ res_id = 0;
+ pseudo_phys_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &res_id, VGA_MEM_BASE, VGA_MEM_BASE + VGA_MEM_SIZE,
+ VGA_MEM_SIZE, RF_ACTIVE);
+ if (pseudo_phys_res == NULL)
+ panic("Unable to reserve vt_vga memory");
+ return (0);
+}
+
+/*-------------------- Private Device Attachment Data -----------------------*/
+static device_method_t vtvga_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, vtvga_identify),
+ DEVMETHOD(device_probe, vtvga_probe),
+ DEVMETHOD(device_attach, vtvga_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(vtvga, vtvga_driver, vtvga_methods, 0);
+devclass_t vtvga_devclass;
+
+DRIVER_MODULE(vtvga, nexus, vtvga_driver, vtvga_devclass, NULL, NULL);
diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h
index 262ffaf..67fcf1e 100644
--- a/sys/dev/vt/vt.h
+++ b/sys/dev/vt/vt.h
@@ -155,6 +155,7 @@ struct vt_device {
int vd_keyboard; /* (G) Keyboard index. */
unsigned int vd_kbstate; /* (?) Device unit. */
unsigned int vd_unit; /* (c) Device unit. */
+ int vd_altbrk; /* (?) Alt break seq. state */
};
#define VD_PASTEBUF(vd) ((vd)->vd_pastebuf.vpb_buf)
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 6d31fae..51c4623 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -825,7 +825,9 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
terminal_input_char(vw->vw_terminal, 0x1b);
}
#endif
-
+#if defined(KDB)
+ kdb_alt_break(c, &vd->vd_altbrk);
+#endif
terminal_input_char(vw->vw_terminal, KEYCHAR(c));
} else
terminal_input_raw(vw->vw_terminal, c);
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index e94fa74..accb46c 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -2564,7 +2564,7 @@ wpi_scan(struct wpi_softc *sc)
struct ieee80211_channel *c;
enum ieee80211_phymode mode;
uint8_t *frm;
- int nrates, pktlen, error, i, nssid;
+ int pktlen, error, i, nssid;
bus_addr_t physaddr;
desc = &ring->desc[ring->cur];
@@ -2613,7 +2613,7 @@ wpi_scan(struct wpi_softc *sc)
nssid = MIN(ss->ss_nssid, WPI_SCAN_MAX_ESSIDS);
for (i = 0; i < nssid; i++) {
hdr->scan_essids[i].id = IEEE80211_ELEMID_SSID;
- hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, 32);
+ hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, IEEE80211_NWID_LEN);
memcpy(hdr->scan_essids[i].essid, ss->ss_ssid[i].ssid,
hdr->scan_essids[i].esslen);
#ifdef WPI_DEBUG
@@ -2630,7 +2630,7 @@ wpi_scan(struct wpi_softc *sc)
* Build a probe request frame. Most of the following code is a
* copy & paste of what is done in net80211.
*/
- wh = (struct ieee80211_frame *)&hdr->scan_essids[4];
+ wh = (struct ieee80211_frame *)&hdr->scan_essids[WPI_SCAN_MAX_ESSIDS];
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
@@ -2642,30 +2642,12 @@ wpi_scan(struct wpi_softc *sc)
frm = (uint8_t *)(wh + 1);
- /* add essid IE, the hardware will fill this in for us */
- *frm++ = IEEE80211_ELEMID_SSID;
- *frm++ = 0;
-
mode = ieee80211_chan2mode(ic->ic_curchan);
rs = &ic->ic_sup_rates[mode];
- /* add supported rates IE */
- *frm++ = IEEE80211_ELEMID_RATES;
- nrates = rs->rs_nrates;
- if (nrates > IEEE80211_RATE_SIZE)
- nrates = IEEE80211_RATE_SIZE;
- *frm++ = nrates;
- memcpy(frm, rs->rs_rates, nrates);
- frm += nrates;
-
- /* add supported xrates IE */
- if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
- nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
- *frm++ = IEEE80211_ELEMID_XRATES;
- *frm++ = nrates;
- memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
- frm += nrates;
- }
+ frm = ieee80211_add_ssid(frm, NULL, 0);
+ frm = ieee80211_add_rates(frm, rs);
+ frm = ieee80211_add_xrates(frm, rs);
/* setup length of probe request */
hdr->tx.len = htole16(frm - (uint8_t *)wh);
diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h
index df71b3d..60d183a 100644
--- a/sys/dev/wpi/if_wpireg.h
+++ b/sys/dev/wpi/if_wpireg.h
@@ -511,7 +511,7 @@ struct {
struct {
uint8_t id;
uint8_t esslen;
- uint8_t essid[32];
+ uint8_t essid[IEEE80211_NWID_LEN];
}scan_essids[WPI_SCAN_MAX_ESSIDS];
/* followed by probe request body */
/* followed by nchan x wpi_scan_chan */
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index 899ae79..5baca5a 100644
--- a/sys/fs/ext2fs/ext2_vnops.c
+++ b/sys/fs/ext2fs/ext2_vnops.c
@@ -239,8 +239,10 @@ ext2_create(struct vop_create_args *ap)
error =
ext2_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
ap->a_dvp, ap->a_vpp, ap->a_cnp);
- if (error)
+ if (error != 0)
return (error);
+ if ((ap->a_cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
return (0);
}
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index a60fa13..3294656 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -184,6 +184,8 @@ msdosfs_create(ap)
if (error)
goto bad;
*ap->a_vpp = DETOV(dep);
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
return (0);
bad:
diff --git a/sys/fs/nandfs/nandfs_vnops.c b/sys/fs/nandfs/nandfs_vnops.c
index 65dcf64..40dd855 100644
--- a/sys/fs/nandfs/nandfs_vnops.c
+++ b/sys/fs/nandfs/nandfs_vnops.c
@@ -1411,6 +1411,8 @@ nandfs_create(struct vop_create_args *ap)
return (error);
}
*vpp = NTOV(node);
+ if ((cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(dvp, *vpp, cnp);
DPRINTF(VNCALL, ("created file vp %p nandnode %p ino %jx\n", *vpp, node,
(uintmax_t)node->nn_ino));
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index 363ff89..c1d50f4 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -260,7 +260,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog,
nrp->nr_vers, sndreserve, rcvreserve);
- CLNT_CONTROL(client, CLSET_WAITCHAN, "newnfsreq");
+ CLNT_CONTROL(client, CLSET_WAITCHAN, "nfsreq");
if (nmp != NULL) {
if ((nmp->nm_flag & NFSMNT_INT))
CLNT_CONTROL(client, CLSET_INTERRUPTIBLE, &one);
@@ -1166,10 +1166,10 @@ nfs_msg(struct thread *td, const char *server, const char *msg, int error)
p = td ? td->td_proc : NULL;
if (error) {
- tprintf(p, LOG_INFO, "newnfs server %s: %s, error %d\n",
+ tprintf(p, LOG_INFO, "nfs server %s: %s, error %d\n",
server, msg, error);
} else {
- tprintf(p, LOG_INFO, "newnfs server %s: %s\n", server, msg);
+ tprintf(p, LOG_INFO, "nfs server %s: %s\n", server, msg);
}
return (0);
}
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index d9f8436..0f6db32 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -219,7 +219,8 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
}
mbufcp = NFSMTOD(mp, caddr_t);
len = mbuf_len(mp);
- KASSERT(len > 0, ("len %d", len));
+ KASSERT(len >= 0,
+ ("len %d, corrupted mbuf?", len));
}
xfer = (left > len) ? len : left;
#ifdef notdef
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index 88c7a34..9f08854 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -930,24 +930,6 @@ void nfsd_mntinit(void);
int newnfs_iosize(struct nfsmount *);
-#ifdef NFS_DEBUG
-
-extern int nfs_debug;
-#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
-#define NFS_DEBUG_WG 2 /* server write gathering */
-#define NFS_DEBUG_RC 4 /* server request caching */
-
-#define NFS_DPF(cat, args) \
- do { \
- if (nfs_debug & NFS_DEBUG_##cat) printf args; \
- } while (0)
-
-#else
-
-#define NFS_DPF(cat, args)
-
-#endif
-
int newnfs_vncmpf(struct vnode *, void *);
#ifndef NFS_MINDIRATTRTIMO
diff --git a/sys/fs/nfsclient/nfs.h b/sys/fs/nfsclient/nfs.h
index 183515c..e05e553 100644
--- a/sys/fs/nfsclient/nfs.h
+++ b/sys/fs/nfsclient/nfs.h
@@ -55,6 +55,24 @@
#define NFS_ISV34(v) \
(VFSTONFS((v)->v_mount)->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4))
+#ifdef NFS_DEBUG
+
+extern int nfs_debug;
+#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
+#define NFS_DEBUG_WG 2 /* server write gathering */
+#define NFS_DEBUG_RC 4 /* server request caching */
+
+#define NFS_DPF(cat, args) \
+ do { \
+ if (nfs_debug & NFS_DEBUG_##cat) printf args; \
+ } while (0)
+
+#else
+
+#define NFS_DPF(cat, args)
+
+#endif
+
/*
* NFS iod threads can be in one of these three states once spawned.
* NFSIOD_NOT_AVAILABLE - Cannot be assigned an I/O operation at this time.
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c
index 5052261..b1a3451 100644
--- a/sys/fs/nfsclient/nfs_clnode.c
+++ b/sys/fs/nfsclient/nfs_clnode.c
@@ -122,7 +122,7 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize, struct nfsnode **npp,
}
np = uma_zalloc(newnfsnode_zone, M_WAITOK | M_ZERO);
- error = getnewvnode("newnfs", mntp, &newnfs_vnodeops, &nvp);
+ error = getnewvnode("nfs", mntp, &newnfs_vnodeops, &nvp);
if (error) {
uma_zfree(newnfsnode_zone, np);
return (error);
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 8529c76..efdc812 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -198,7 +198,7 @@ nfscl_nget(struct mount *mntp, struct vnode *dvp, struct nfsfh *nfhp,
}
np = uma_zalloc(newnfsnode_zone, M_WAITOK | M_ZERO);
- error = getnewvnode("newnfs", mntp, &newnfs_vnodeops, &nvp);
+ error = getnewvnode("nfs", mntp, &newnfs_vnodeops, &nvp);
if (error) {
uma_zfree(newnfsnode_zone, np);
FREE((caddr_t)nfhp, M_NFSFH);
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index 33f92c6..9758b4c 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -100,6 +100,11 @@ SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
+#ifdef NFS_DEBUG
+int nfs_debug;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
+ "Toggle debug flag");
+#endif
static int nfs_mountroot(struct mount *);
static void nfs_sec_name(char *, int *);
@@ -152,7 +157,7 @@ MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
* will be defined for kernels built without NFS_ROOT, although it
* isn't used in that case.
*/
-#if !defined(NFS_ROOT) && !defined(NFSCLIENT)
+#if !defined(NFS_ROOT)
struct nfs_diskless nfs_diskless = { { { 0 } } };
struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
int nfs_diskless_valid = 0;
@@ -704,7 +709,7 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
while (newnfs_connect(nmp, &nmp->nm_sockreq,
cred, td, 0)) {
printf("newnfs_args: retrying connect\n");
- (void) nfs_catnap(PSOCK, 0, "newnfscon");
+ (void) nfs_catnap(PSOCK, 0, "nfscon");
}
}
} else {
@@ -1063,7 +1068,7 @@ nfs_mount(struct mount *mp)
* greater than NFS_MAXDGRAMDATA, those thread(s) will be
* hung, retrying the RPC(s) forever. Usually these threads
* will be seen doing an uninterruptible sleep on wait channel
- * "newnfsreq" (truncated to "newnfsre" by procstat).
+ * "nfsreq".
*/
if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
tprintf(td->td_proc, LOG_WARNING,
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 818551f..513abf4 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1606,20 +1606,6 @@ again:
}
} else if (NFS_ISV34(dvp) && (fmode & O_EXCL)) {
if (nfscl_checksattr(vap, &nfsva)) {
- /*
- * We are normally called with only a partially
- * initialized VAP. Since the NFSv3 spec says that
- * the server may use the file attributes to
- * store the verifier, the spec requires us to do a
- * SETATTR RPC. FreeBSD servers store the verifier in
- * atime, but we can't really assume that all servers
- * will so we ensure that our SETATTR sets both atime
- * and mtime.
- */
- if (vap->va_mtime.tv_sec == VNOVAL)
- vfs_timestamp(&vap->va_mtime);
- if (vap->va_atime.tv_sec == VNOVAL)
- vap->va_atime = vap->va_mtime;
error = nfsrpc_setattr(newvp, vap, NULL, cnp->cn_cred,
cnp->cn_thread, &nfsva, &attrflag, NULL);
if (error && (vap->va_uid != (uid_t)VNOVAL ||
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 5bd4538..17ca5a6 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -2970,12 +2970,7 @@ nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
if (nfsrv_dolocallocks == 0)
goto out;
-
- /* Check for VI_DOOMED here, so that VOP_ADVLOCK() isn't performed. */
- if ((vp->v_iflag & VI_DOOMED) != 0) {
- error = EPERM;
- goto out;
- }
+ ASSERT_VOP_UNLOCKED(vp, "nfsvno_advlock: vp locked");
fl.l_whence = SEEK_SET;
fl.l_type = ftype;
@@ -2999,14 +2994,12 @@ nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
fl.l_pid = (pid_t)0;
fl.l_sysid = (int)nfsv4_sysid;
- NFSVOPUNLOCK(vp, 0);
if (ftype == F_UNLCK)
error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl,
(F_POSIX | F_REMOTE));
else
error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl,
(F_POSIX | F_REMOTE));
- NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
out:
NFSEXITCODE(error);
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 97f8fff..5e9beeb 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -1344,6 +1344,8 @@ nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
vnode_t tvp = NULL;
uint64_t first, end;
+ if (vp != NULL)
+ ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked");
lop = LIST_FIRST(&stp->ls_lock);
while (lop != LIST_END(&stp->ls_lock)) {
nlop = LIST_NEXT(lop, lo_lckowner);
@@ -1363,9 +1365,10 @@ nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
if (gottvp == 0) {
if (nfsrv_dolocallocks == 0)
tvp = NULL;
- else if (vp == NULL && cansleep != 0)
+ else if (vp == NULL && cansleep != 0) {
tvp = nfsvno_getvp(&lfp->lf_fh);
- else
+ NFSVOPUNLOCK(tvp, 0);
+ } else
tvp = vp;
gottvp = 1;
}
@@ -1386,7 +1389,7 @@ nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
lop = nlop;
}
if (vp == NULL && tvp != NULL)
- vput(tvp);
+ vrele(tvp);
}
/*
@@ -1497,7 +1500,7 @@ nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
struct nfsclient *clp = NULL;
u_int32_t bits;
int error = 0, haslock = 0, ret, reterr;
- int getlckret, delegation = 0, filestruct_locked;
+ int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0;
fhandle_t nfh;
uint64_t first, end;
uint32_t lock_flags;
@@ -1587,6 +1590,11 @@ tryagain:
* locking rolled back.
*/
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1");
+ vnode_unlocked = 1;
+ NFSVOPUNLOCK(vp, 0);
+ }
reterr = nfsrv_locallock(vp, lfp,
(new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)),
new_lop->lo_first, new_lop->lo_end, cfp, p);
@@ -1756,6 +1764,11 @@ tryagain:
if (filestruct_locked != 0) {
/* Roll back local locks. */
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2");
+ vnode_unlocked = 1;
+ NFSVOPUNLOCK(vp, 0);
+ }
nfsrv_locallock_rollback(vp, lfp, p);
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
@@ -1833,6 +1846,12 @@ tryagain:
if (filestruct_locked != 0) {
/* Roll back local locks. */
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp,
+ "nfsrv_lockctrl3");
+ vnode_unlocked = 1;
+ NFSVOPUNLOCK(vp, 0);
+ }
nfsrv_locallock_rollback(vp, lfp, p);
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
@@ -1852,6 +1871,8 @@ tryagain:
bits = tstp->ls_flags;
bits >>= NFSLCK_SHIFT;
if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
+ KASSERT(vnode_unlocked == 0,
+ ("nfsrv_lockctrl: vnode unlocked1"));
ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
vp, p);
if (ret == 1) {
@@ -1883,6 +1904,8 @@ tryagain:
* For setattr, just get rid of all the Delegations for other clients.
*/
if (new_stp->ls_flags & NFSLCK_SETATTR) {
+ KASSERT(vnode_unlocked == 0,
+ ("nfsrv_lockctrl: vnode unlocked2"));
ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
if (ret) {
/*
@@ -1933,14 +1956,26 @@ tryagain:
(new_lop->lo_flags & NFSLCK_WRITE) &&
(clp != tstp->ls_clp ||
(tstp->ls_flags & NFSLCK_DELEGREAD)))) {
+ ret = 0;
if (filestruct_locked != 0) {
/* Roll back local locks. */
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4");
+ NFSVOPUNLOCK(vp, 0);
+ }
nfsrv_locallock_rollback(vp, lfp, p);
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
+ NFSUNLOCKSTATE();
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+ vnode_unlocked = 0;
+ if ((vp->v_iflag & VI_DOOMED) != 0)
+ ret = NFSERR_SERVERFAULT;
+ NFSLOCKSTATE();
}
- ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
+ if (ret == 0)
+ ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
if (ret) {
/*
* nfsrv_delegconflict unlocks state when it
@@ -1979,6 +2014,11 @@ tryagain:
stateidp->other[2] = stp->ls_stateid.other[2];
if (filestruct_locked != 0) {
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5");
+ vnode_unlocked = 1;
+ NFSVOPUNLOCK(vp, 0);
+ }
/* Update the local locks. */
nfsrv_localunlock(vp, lfp, first, end, p);
NFSLOCKSTATE();
@@ -2009,14 +2049,29 @@ tryagain:
FREE((caddr_t)other_lop, M_NFSDLOCK);
other_lop = NULL;
}
- ret = nfsrv_clientconflict(lop->lo_stp->ls_clp,&haslock,vp,p);
+ if (vnode_unlocked != 0)
+ ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
+ NULL, p);
+ else
+ ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
+ vp, p);
if (ret == 1) {
if (filestruct_locked != 0) {
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6");
+ NFSVOPUNLOCK(vp, 0);
+ }
/* Roll back local locks. */
nfsrv_locallock_rollback(vp, lfp, p);
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
NFSUNLOCKSTATE();
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+ vnode_unlocked = 0;
+ if ((vp->v_iflag & VI_DOOMED) != 0) {
+ error = NFSERR_SERVERFAULT;
+ goto out;
+ }
}
/*
* nfsrv_clientconflict() unlocks state when it
@@ -2050,6 +2105,11 @@ tryagain:
if (filestruct_locked != 0 && ret == 0) {
/* Roll back local locks. */
NFSUNLOCKSTATE();
+ if (vnode_unlocked == 0) {
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7");
+ vnode_unlocked = 1;
+ NFSVOPUNLOCK(vp, 0);
+ }
nfsrv_locallock_rollback(vp, lfp, p);
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
@@ -2128,6 +2188,11 @@ out:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
+ if (vnode_unlocked != 0) {
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+ if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
+ error = NFSERR_SERVERFAULT;
+ }
if (other_lop)
FREE((caddr_t)other_lop, M_NFSDLOCK);
NFSEXITCODE2(error, nd);
@@ -3235,11 +3300,14 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
/* Get the lf lock */
nfsrv_locklf(lfp);
NFSUNLOCKSTATE();
+ ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate");
+ NFSVOPUNLOCK(vp, 0);
if (nfsrv_freeopen(stp, vp, 1, p) == 0) {
NFSLOCKSTATE();
nfsrv_unlocklf(lfp);
NFSUNLOCKSTATE();
}
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
} else {
(void) nfsrv_freeopen(stp, NULL, 0, p);
NFSUNLOCKSTATE();
@@ -4627,7 +4695,7 @@ static int
nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
NFSPROC_T *p)
{
- int gotlock, lktype;
+ int gotlock, lktype = 0;
/*
* If lease hasn't expired, we can't fix it.
@@ -4637,8 +4705,10 @@ nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
return (0);
if (*haslockp == 0) {
NFSUNLOCKSTATE();
- lktype = NFSVOPISLOCKED(vp);
- NFSVOPUNLOCK(vp, 0);
+ if (vp != NULL) {
+ lktype = NFSVOPISLOCKED(vp);
+ NFSVOPUNLOCK(vp, 0);
+ }
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsv4rootfs_lock);
do {
@@ -4647,11 +4717,12 @@ nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
} while (!gotlock);
NFSUNLOCKV4ROOTMUTEX();
*haslockp = 1;
- NFSVOPLOCK(vp, lktype | LK_RETRY);
- if ((vp->v_iflag & VI_DOOMED) != 0)
- return (2);
- else
- return (1);
+ if (vp != NULL) {
+ NFSVOPLOCK(vp, lktype | LK_RETRY);
+ if ((vp->v_iflag & VI_DOOMED) != 0)
+ return (2);
+ }
+ return (1);
}
NFSUNLOCKSTATE();
@@ -4692,7 +4763,7 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
vnode_t vp)
{
struct nfsclient *clp = stp->ls_clp;
- int gotlock, error, lktype, retrycnt, zapped_clp;
+ int gotlock, error, lktype = 0, retrycnt, zapped_clp;
nfsv4stateid_t tstateid;
fhandle_t tfh;
@@ -4809,8 +4880,10 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
*/
if (*haslockp == 0) {
NFSUNLOCKSTATE();
- lktype = NFSVOPISLOCKED(vp);
- NFSVOPUNLOCK(vp, 0);
+ if (vp != NULL) {
+ lktype = NFSVOPISLOCKED(vp);
+ NFSVOPUNLOCK(vp, 0);
+ }
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsv4rootfs_lock);
do {
@@ -4819,14 +4892,16 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
} while (!gotlock);
NFSUNLOCKV4ROOTMUTEX();
*haslockp = 1;
- NFSVOPLOCK(vp, lktype | LK_RETRY);
- if ((vp->v_iflag & VI_DOOMED) != 0) {
- *haslockp = 0;
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- error = NFSERR_PERM;
- goto out;
+ if (vp != NULL) {
+ NFSVOPLOCK(vp, lktype | LK_RETRY);
+ if ((vp->v_iflag & VI_DOOMED) != 0) {
+ *haslockp = 0;
+ NFSLOCKV4ROOTMUTEX();
+ nfsv4_unlock(&nfsv4rootfs_lock, 1);
+ NFSUNLOCKV4ROOTMUTEX();
+ error = NFSERR_PERM;
+ goto out;
+ }
}
error = -1;
goto out;
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 29ee389..c811b9a 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -213,10 +213,14 @@ tmpfs_create(struct vop_create_args *v)
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct vattr *vap = v->a_vap;
+ int error;
MPASS(vap->va_type == VREG || vap->va_type == VSOCK);
- return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
+ error = tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
+ if (error == 0 && (cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(dvp, *vpp, cnp);
+ return (error);
}
static int
diff --git a/sys/geom/sched/README b/sys/geom/sched/README
index 1b52d90..b62d468 100644
--- a/sys/geom/sched/README
+++ b/sys/geom/sched/README
@@ -39,37 +39,17 @@ with cvs, and lets cvs progress when competing with a writer.
To try it out:
-1. USERS OF FREEBSD 7, PLEASE READ CAREFULLY THE FOLLOWING:
-
- On loading, this module patches one kernel function (g_io_request())
- so that I/O requests ("bio's") carry a classification tag, useful
- for scheduling purposes.
-
- ON FREEBSD 7, the tag is stored in an existing (though rarely used)
- field of the "struct bio", a solution which makes this module
- incompatible with other modules using it, such as ZFS and gjournal.
- Additionally, g_io_request() is patched in-memory to add a call
- to the function that initializes this field (i386/amd64 only;
- for other architectures you need to manually patch sys/geom/geom_io.c).
- See details in the file g_sched.c.
-
- On FreeBSD 8.0 and above, the above trick is not necessary,
- as the struct bio contains dedicated fields for the classifier,
- and hooks for request classifiers.
-
- If you don't like the above, don't run this code.
-
-2. PLEASE MAKE SURE THAT THE DISK THAT YOU WILL BE USING FOR TESTS
+1. PLEASE MAKE SURE THAT THE DISK THAT YOU WILL BE USING FOR TESTS
DOES NOT CONTAIN PRECIOUS DATA.
This is experimental code, so we make no guarantees, though
I am routinely using it on my desktop and laptop.
-3. EXTRACT AND BUILD THE PROGRAMS
+2. EXTRACT AND BUILD THE PROGRAMS
A 'make install' in the directory should work (with root privs),
or you can even try the binary modules.
If you want to build the modules yourself, look at the Makefile.
-4. LOAD THE MODULE, CREATE A GEOM NODE, RUN TESTS
+3. LOAD THE MODULE, CREATE A GEOM NODE, RUN TESTS
The scheduler's module must be loaded first:
diff --git a/sys/geom/sched/g_sched.c b/sys/geom/sched/g_sched.c
index 009a58c..f1c9a3d 100644
--- a/sys/geom/sched/g_sched.c
+++ b/sys/geom/sched/g_sched.c
@@ -346,17 +346,8 @@ static inline u_long
g_sched_classify(struct bio *bp)
{
-#if __FreeBSD_version > 800098
/* we have classifier fields in the struct bio */
-#define HAVE_BIO_CLASSIFIER
return ((u_long)bp->bio_classifier1);
-#else
-#warning old version!!!
- while (bp->bio_parent != NULL)
- bp = bp->bio_parent;
-
- return ((u_long)bp->bio_caller1);
-#endif
}
/* Return the hash chain for the given key. */
@@ -705,7 +696,7 @@ g_gsched_global_init(void)
G_SCHED_DEBUG(0, "Initializing global data.");
mtx_init(&me.gs_mtx, "gsched", NULL, MTX_DEF);
LIST_INIT(&me.gs_scheds);
- gs_bioq_init(&me.gs_pending);
+ bioq_init(&me.gs_pending);
me.gs_initialized = 1;
}
}
@@ -914,7 +905,7 @@ g_sched_temporary_start(struct bio *bio)
mtx_lock(&me.gs_mtx);
me.gs_npending++;
- gs_bioq_disksort(&me.gs_pending, bio);
+ bioq_disksort(&me.gs_pending, bio);
mtx_unlock(&me.gs_mtx);
}
@@ -923,7 +914,7 @@ g_sched_flush_pending(g_start_t *start)
{
struct bio *bp;
- while ((bp = gs_bioq_takefirst(&me.gs_pending)))
+ while ((bp = bioq_takefirst(&me.gs_pending)))
start(bp);
}
@@ -1365,161 +1356,7 @@ g_sched_destroy_geom(struct gctl_req *req, struct g_class *mp,
* to the issuer of a request in bp->bio_classifier1 as soon
* as the bio is posted to the geom queue (and not later, because
* requests are managed by the g_down thread afterwards).
- *
- * On older versions of the system (but this code is not used
- * in any existing release), we [ab]use the caller1 field in the
- * root element of the bio tree to store the classification info.
- * The marking is done at the beginning of g_io_request()
- * and only if we find that the field is NULL.
- *
- * To avoid rebuilding the kernel, this module will patch the
- * initial part of g_io_request() so it jumps to some hand-coded
- * assembly that does the marking and then executes the original
- * body of g_io_request().
- *
- * fake_ioreq[] is architecture-specific machine code
- * that implements the above. CODE_SIZE, STORE_SIZE etc.
- * are constants used in the patching routine. Look at the
- * code in g_ioreq_patch() for the details.
- */
-
-#ifndef HAVE_BIO_CLASSIFIER
-/*
- * Support for old FreeBSD versions
*/
-#if defined(__i386__)
-#define CODE_SIZE 29
-#define STORE_SIZE 5
-#define EPILOGUE 5
-#define SIZE (CODE_SIZE + STORE_SIZE + EPILOGUE)
-
-static u_char fake_ioreq[SIZE] = {
- 0x8b, 0x44, 0x24, 0x04, /* mov bp, %eax */
- /* 1: */
- 0x89, 0xc2, /* mov %eax, %edx # edx = bp */
- 0x8b, 0x40, 0x64, /* mov bp->bio_parent, %eax */
- 0x85, 0xc0, /* test %eax, %eax */
- 0x75, 0xf7, /* jne 1b */
- 0x8b, 0x42, 0x30, /* mov bp->bp_caller1, %eax */
- 0x85, 0xc0, /* test %eax, %eax */
- 0x75, 0x09, /* jne 2f */
- 0x64, 0xa1, 0x00, 0x00, /* mov %fs:0, %eax */
- 0x00, 0x00,
- 0x89, 0x42, 0x30, /* mov %eax, bp->bio_caller1 */
- /* 2: */
- 0x55, 0x89, 0xe5, 0x57, 0x56,
- 0xe9, 0x00, 0x00, 0x00, 0x00, /* jmp back... */
-};
-#elif defined(__amd64)
-#define CODE_SIZE 38
-#define STORE_SIZE 6
-#define EPILOGUE 5
-#define SIZE (CODE_SIZE + STORE_SIZE + EPILOGUE)
-
-static u_char fake_ioreq[SIZE] = {
- 0x48, 0x89, 0xf8, /* mov bp, %rax */
- /* 1: */
- 0x48, 0x89, 0xc2, /* mov %rax, %rdx # rdx = bp */
- 0x48, 0x8b, 0x82, 0xa8, /* mov bp->bio_parent, %rax */
- 0x00, 0x00, 0x00,
- 0x48, 0x85, 0xc0, /* test %rax, %rax */
- 0x75, 0xf1, /* jne 1b */
- 0x48, 0x83, 0x7a, 0x58, /* cmp $0, bp->bp_caller1 */
- 0x00,
- 0x75, 0x0d, /* jne 2f */
- 0x65, 0x48, 0x8b, 0x04, /* mov %gs:0, %rax */
- 0x25, 0x00, 0x00, 0x00,
- 0x00,
- 0x48, 0x89, 0x42, 0x58, /* mov %rax, bp->bio_caller1 */
- /* 2: */
- 0x55, 0x48, 0x89, 0xe5, 0x41, 0x56,
- 0xe9, 0x00, 0x00, 0x00, 0x00, /* jmp back... */
-};
-#else /* neither x86 nor amd64 */
-static void
-g_new_io_request(struct bio *bp, struct g_consumer *cp)
-{
- struct bio *top = bp;
-
- /*
- * bio classification: if bio_caller1 is available in the
- * root of the 'struct bio' tree, store there the thread id
- * of the thread that originated the request.
- * More sophisticated classification schemes can be used.
- */
- while (top->bio_parent)
- top = top->bio_parent;
-
- if (top->bio_caller1 == NULL)
- top->bio_caller1 = curthread;
-}
-
-#error please add the code above in g_new_io_request() to the beginning of \
- /sys/geom/geom_io.c::g_io_request(), and remove this line.
-#endif /* end of arch-specific code */
-
-static int
-g_ioreq_patch(void)
-{
- u_char *original;
- u_long ofs;
- int found;
-
- if (me.gs_patched)
- return (-1);
-
- original = (u_char *)g_io_request;
-
- found = !bcmp(original, fake_ioreq + CODE_SIZE, STORE_SIZE);
- if (!found)
- return (-1);
-
- /* Jump back to the original + STORE_SIZE. */
- ofs = (original + STORE_SIZE) - (fake_ioreq + SIZE);
- bcopy(&ofs, fake_ioreq + CODE_SIZE + STORE_SIZE + 1, 4);
-
- /* Patch the original address with a jump to the trampoline. */
- *original = 0xe9; /* jump opcode */
- ofs = fake_ioreq - (original + 5);
- bcopy(&ofs, original + 1, 4);
-
- me.gs_patched = 1;
-
- return (0);
-}
-
-/*
- * Restore the original code, this is easy.
- */
-static void
-g_ioreq_restore(void)
-{
- u_char *original;
-
- if (me.gs_patched) {
- original = (u_char *)g_io_request;
- bcopy(fake_ioreq + CODE_SIZE, original, STORE_SIZE);
- me.gs_patched = 0;
- }
-}
-
-static inline void
-g_classifier_ini(void)
-{
-
- g_ioreq_patch();
-}
-
-static inline void
-g_classifier_fini(void)
-{
-
- g_ioreq_restore();
-}
-
-/*--- end of support code for older FreeBSD versions */
-
-#else /* HAVE_BIO_CLASSIFIER */
/*
* Classifier support for recent FreeBSD versions: we use
@@ -1552,7 +1389,6 @@ g_classifier_fini(void)
g_unregister_classifier(&g_sched_classifier);
}
-#endif /* HAVE_BIO_CLASSIFIER */
static void
g_sched_init(struct g_class *mp)
diff --git a/sys/geom/sched/g_sched.h b/sys/geom/sched/g_sched.h
index 3a34e29..9fdadc4 100644
--- a/sys/geom/sched/g_sched.h
+++ b/sys/geom/sched/g_sched.h
@@ -120,19 +120,6 @@ struct g_sched_softc {
#define G_SCHED_PROXYING 1
#define G_SCHED_FLUSHING 2
-/*
- * Temporary- our own version of the disksort, because the
- * version in 7.x and 8.x before march 2009 is buggy.
- */
-void gs_bioq_init(struct bio_queue_head *);
-void gs_bioq_remove(struct bio_queue_head *, struct bio *);
-void gs_bioq_flush(struct bio_queue_head *, struct devstat *, int);
-void gs_bioq_insert_head(struct bio_queue_head *, struct bio *);
-void gs_bioq_insert_tail(struct bio_queue_head *, struct bio *);
-struct bio *gs_bioq_first(struct bio_queue_head *);
-struct bio *gs_bioq_takefirst(struct bio_queue_head *);
-void gs_bioq_disksort(struct bio_queue_head *, struct bio *);
-
#endif /* _KERNEL */
#endif /* _G_SCHED_H_ */
diff --git a/sys/geom/sched/gs_rr.c b/sys/geom/sched/gs_rr.c
index 6f26879..b9d5d1b 100644
--- a/sys/geom/sched/gs_rr.c
+++ b/sys/geom/sched/gs_rr.c
@@ -315,7 +315,7 @@ g_rr_init_class(void *data, void *priv)
struct g_rr_softc *sc = data;
struct g_rr_queue *qp = priv;
- gs_bioq_init(&qp->q_bioq);
+ bioq_init(&qp->q_bioq);
/*
* Set the initial parameters for the client:
@@ -350,7 +350,7 @@ g_rr_fini_class(void *data, void *priv)
{
struct g_rr_queue *qp = priv;
- KASSERT(gs_bioq_first(&qp->q_bioq) == NULL,
+ KASSERT(bioq_first(&qp->q_bioq) == NULL,
("released nonempty queue"));
qp->q_sc->sc_nqueues--;
me.queues--;
@@ -438,7 +438,7 @@ g_rr_next(void *data, int force)
qp->q_flags &= ~G_FLAG_COMPLETED;
}
- bp = gs_bioq_takefirst(&qp->q_bioq); /* surely not NULL */
+ bp = bioq_takefirst(&qp->q_bioq); /* surely not NULL */
qp->q_service += bp->bio_length; /* charge the service */
/*
@@ -456,7 +456,7 @@ g_rr_next(void *data, int force)
* on read or writes (e.g., anticipate only on reads).
*/
expired = g_rr_queue_expired(qp); /* are we expired ? */
- next = gs_bioq_first(&qp->q_bioq); /* do we have one more ? */
+ next = bioq_first(&qp->q_bioq); /* do we have one more ? */
if (expired) {
sc->sc_active = NULL;
/* Either requeue or release reference. */
@@ -538,7 +538,7 @@ g_rr_start(void *data, struct bio *bp)
if (qp == NULL)
return (-1); /* allocation failed, tell upstream */
- if (gs_bioq_first(&qp->q_bioq) == NULL) {
+ if (bioq_first(&qp->q_bioq) == NULL) {
/*
* We are inserting into an empty queue.
* Reset its state if it is sc_active,
@@ -560,7 +560,7 @@ g_rr_start(void *data, struct bio *bp)
/* Inherit the reference returned by g_rr_queue_get(). */
bp->bio_caller1 = qp;
- gs_bioq_disksort(&qp->q_bioq, bp);
+ bioq_disksort(&qp->q_bioq, bp);
return (0);
}
diff --git a/sys/geom/sched/subr_disk.c b/sys/geom/sched/subr_disk.c
deleted file mode 100644
index db2a9ef..0000000
--- a/sys/geom/sched/subr_disk.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*-
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * The bioq_disksort() (and the specification of the bioq API)
- * have been written by Luigi Rizzo and Fabio Checconi under the same
- * license as above.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-//#include "opt_geom.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/conf.h>
-#include <sys/disk.h>
-#include <geom/geom_disk.h>
-#include "g_sched.h"
-
-/*
- * BIO queue implementation
- *
- * Please read carefully the description below before making any change
- * to the code, or you might change the behaviour of the data structure
- * in undesirable ways.
- *
- * A bioq stores disk I/O request (bio), normally sorted according to
- * the distance of the requested position (bio->bio_offset) from the
- * current head position (bioq->last_offset) in the scan direction, i.e.
- *
- * (uoff_t)(bio_offset - last_offset)
- *
- * Note that the cast to unsigned (uoff_t) is fundamental to insure
- * that the distance is computed in the scan direction.
- *
- * The main methods for manipulating the bioq are:
- *
- * bioq_disksort() performs an ordered insertion;
- *
- * bioq_first() return the head of the queue, without removing;
- *
- * bioq_takefirst() return and remove the head of the queue,
- * updating the 'current head position' as
- * bioq->last_offset = bio->bio_offset + bio->bio_length;
- *
- * When updating the 'current head position', we assume that the result of
- * bioq_takefirst() is dispatched to the device, so bioq->last_offset
- * represents the head position once the request is complete.
- *
- * If the bioq is manipulated using only the above calls, it starts
- * with a sorted sequence of requests with bio_offset >= last_offset,
- * possibly followed by another sorted sequence of requests with
- * 0 <= bio_offset < bioq->last_offset
- *
- * NOTE: historical behaviour was to ignore bio->bio_length in the
- * update, but its use tracks the head position in a better way.
- * Historical behaviour was also to update the head position when
- * the request under service is complete, rather than when the
- * request is extracted from the queue. However, the current API
- * has no method to update the head position; secondly, once
- * a request has been submitted to the disk, we have no idea of
- * the actual head position, so the final one is our best guess.
- *
- * --- Direct queue manipulation ---
- *
- * A bioq uses an underlying TAILQ to store requests, so we also
- * export methods to manipulate the TAILQ, in particular:
- *
- * bioq_insert_tail() insert an entry at the end.
- * It also creates a 'barrier' so all subsequent
- * insertions through bioq_disksort() will end up
- * after this entry;
- *
- * bioq_insert_head() insert an entry at the head, update
- * bioq->last_offset = bio->bio_offset so that
- * all subsequent insertions through bioq_disksort()
- * will end up after this entry;
- *
- * bioq_remove() remove a generic element from the queue, act as
- * bioq_takefirst() if invoked on the head of the queue.
- *
- * The semantic of these methods is the same as the operations
- * on the underlying TAILQ, but with additional guarantees on
- * subsequent bioq_disksort() calls. E.g. bioq_insert_tail()
- * can be useful for making sure that all previous ops are flushed
- * to disk before continuing.
- *
- * Updating bioq->last_offset on a bioq_insert_head() guarantees
- * that the bio inserted with the last bioq_insert_head() will stay
- * at the head of the queue even after subsequent bioq_disksort().
- *
- * Note that when the direct queue manipulation functions are used,
- * the queue may contain multiple inversion points (i.e. more than
- * two sorted sequences of requests).
- *
- */
-
-void
-gs_bioq_init(struct bio_queue_head *head)
-{
-
- TAILQ_INIT(&head->queue);
- head->last_offset = 0;
- head->insert_point = NULL;
-}
-
-void
-gs_bioq_remove(struct bio_queue_head *head, struct bio *bp)
-{
-
- if (head->insert_point == NULL) {
- if (bp == TAILQ_FIRST(&head->queue))
- head->last_offset = bp->bio_offset + bp->bio_length;
- } else if (bp == head->insert_point)
- head->insert_point = NULL;
-
- TAILQ_REMOVE(&head->queue, bp, bio_queue);
-}
-
-void
-gs_bioq_flush(struct bio_queue_head *head, struct devstat *stp, int error)
-{
- struct bio *bp;
-
- while ((bp = gs_bioq_takefirst(head)) != NULL)
- biofinish(bp, stp, error);
-}
-
-void
-gs_bioq_insert_head(struct bio_queue_head *head, struct bio *bp)
-{
-
- if (head->insert_point == NULL)
- head->last_offset = bp->bio_offset;
- TAILQ_INSERT_HEAD(&head->queue, bp, bio_queue);
-}
-
-void
-gs_bioq_insert_tail(struct bio_queue_head *head, struct bio *bp)
-{
-
- TAILQ_INSERT_TAIL(&head->queue, bp, bio_queue);
- head->insert_point = bp;
- head->last_offset = bp->bio_offset;
-}
-
-struct bio *
-gs_bioq_first(struct bio_queue_head *head)
-{
-
- return (TAILQ_FIRST(&head->queue));
-}
-
-struct bio *
-gs_bioq_takefirst(struct bio_queue_head *head)
-{
- struct bio *bp;
-
- bp = TAILQ_FIRST(&head->queue);
- if (bp != NULL)
- gs_bioq_remove(head, bp);
- return (bp);
-}
-
-/*
- * Compute the sorting key. The cast to unsigned is
- * fundamental for correctness, see the description
- * near the beginning of the file.
- */
-static inline uoff_t
-gs_bioq_bio_key(struct bio_queue_head *head, struct bio *bp)
-{
-
- return ((uoff_t)(bp->bio_offset - head->last_offset));
-}
-
-/*
- * Seek sort for disks.
- *
- * Sort all requests in a single queue while keeping
- * track of the current position of the disk with last_offset.
- * See above for details.
- */
-void
-gs_bioq_disksort(struct bio_queue_head *head, struct bio *bp)
-{
- struct bio *cur, *prev;
- uoff_t key;
-
- if ((bp->bio_flags & BIO_ORDERED) != 0) {
- /*
- * Ordered transactions can only be dispatched
- * after any currently queued transactions. They
- * also have barrier semantics - no transactions
- * queued in the future can pass them.
- */
- gs_bioq_insert_tail(head, bp);
- return;
- }
-
- prev = NULL;
- key = gs_bioq_bio_key(head, bp);
- cur = TAILQ_FIRST(&head->queue);
-
- if (head->insert_point) {
- prev = head->insert_point;
- cur = TAILQ_NEXT(head->insert_point, bio_queue);
- }
-
- while (cur != NULL && key >= gs_bioq_bio_key(head, cur)) {
- prev = cur;
- cur = TAILQ_NEXT(cur, bio_queue);
- }
-
- if (prev == NULL)
- TAILQ_INSERT_HEAD(&head->queue, bp, bio_queue);
- else
- TAILQ_INSERT_AFTER(&head->queue, prev, bp, bio_queue);
-}
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 490d481..6d35c3a 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -246,7 +246,7 @@ trap(struct trapframe *frame)
* flag is cleared and finally re-scheduling is enabled.
*/
if ((type == T_PROTFLT || type == T_PAGEFLT) &&
- dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
+ dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
goto out;
#endif
diff --git a/sys/i386/xen/clock.c b/sys/i386/xen/clock.c
index 0f5b0e5..26fafee 100644
--- a/sys/i386/xen/clock.c
+++ b/sys/i386/xen/clock.c
@@ -118,7 +118,7 @@ struct mtx clock_lock;
#define RTC_UNLOCK mtx_unlock_spin(&clock_lock)
#define NS_PER_TICK (1000000000ULL/hz)
-int adjkerntz; /* local offset from GMT in seconds */
+int adjkerntz; /* local offset from UTC in seconds */
int clkintr_pending;
int pscnt = 1;
int psdiv = 1;
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index b34eb62..a4f0f88 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3167,7 +3167,8 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
sbuf_delete(&sb);
cmode = S_IRUSR | S_IWUSR;
- oflags = VN_OPEN_NOAUDIT | (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
+ oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
+ (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
/*
* If the core format has a %I in it, then we need to check
diff --git a/sys/kern/subr_fattime.c b/sys/kern/subr_fattime.c
index e2a2195..099479c 100644
--- a/sys/kern/subr_fattime.c
+++ b/sys/kern/subr_fattime.c
@@ -45,7 +45,7 @@
* Later on again, in Windows NT, timestamps were defined relative to GMT.
*
* Purists will point out that UTC replaced GMT for such uses around
- * a century ago, already then. Ironically "NT" was an abbreviation of
+ * half a century ago, already then. Ironically "NT" was an abbreviation of
* "New Technology". Anyway...
*
* The 'utc' argument determines if the resulting FATTIME timestamp
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 537f9c8..88952ed 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -579,7 +579,7 @@ sbappend_locked(struct sockbuf *sb, struct mbuf *m)
if (m == 0)
return;
-
+ m_clrprotoflags(m);
SBLASTRECORDCHK(sb);
n = sb->sb_mb;
if (n) {
@@ -732,6 +732,7 @@ sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0)
if (m0 == 0)
return;
+ m_clrprotoflags(m0);
/*
* Put the first mbuf on the queue. Note this permits zero length
* records.
@@ -777,6 +778,8 @@ sbappendaddr_locked_internal(struct sockbuf *sb, const struct sockaddr *asa,
return (0);
m->m_len = asa->sa_len;
bcopy(asa, mtod(m, caddr_t), asa->sa_len);
+ if (m0)
+ m_clrprotoflags(m0);
if (ctrl_last)
ctrl_last->m_next = m0; /* concatenate data to control */
else
@@ -872,6 +875,7 @@ sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
if (space > sbspace(sb))
return (0);
+ m_clrprotoflags(m0);
n->m_next = m0; /* concatenate data to control */
SBLASTRECORDCHK(sb);
@@ -1062,6 +1066,21 @@ sbcut_internal(struct sockbuf *sb, int len)
m = n;
}
}
+ /*
+ * Free any zero-length mbufs from the buffer.
+ * For SOCK_DGRAM sockets such mbufs represent empty records.
+ * XXX: For SOCK_STREAM sockets such mbufs can appear in the buffer,
+ * when sosend_generic() needs to send only control data.
+ */
+ while (m && m->m_len == 0) {
+ struct mbuf *n;
+
+ sbfree(sb, m);
+ n = m->m_next;
+ m->m_next = mfree;
+ mfree = m;
+ m = n;
+ }
if (m) {
sb->sb_mb = m;
m->m_nextpkt = next;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index f08036d..189a30f 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1310,11 +1310,14 @@ restart:
resid = 0;
if (flags & MSG_EOR)
top->m_flags |= M_EOR;
- } else if (resid > 0) {
+ } else {
/*
* Copy the data from userland into a mbuf
- * chain. If no data is to be copied in,
- * a single empty mbuf is returned.
+ * chain. If resid is 0, which can happen
+ * only if we have control to send, then
+ * a single empty mbuf is returned. This
+ * is a workaround to prevent protocol send
+ * methods to panic.
*/
top = m_uiotombuf(uio, M_WAITOK, space,
(atomic ? max_hdr : 0),
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index a34be50..d6b3765 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -401,17 +401,24 @@ int
vop_stdadvlock(struct vop_advlock_args *ap)
{
struct vnode *vp;
- struct ucred *cred;
struct vattr vattr;
int error;
vp = ap->a_vp;
- cred = curthread->td_ucred;
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_GETATTR(vp, &vattr, cred);
- VOP_UNLOCK(vp, 0);
- if (error)
- return (error);
+ if (ap->a_fl->l_whence == SEEK_END) {
+ /*
+ * The NFSv4 server must avoid doing a vn_lock() here, since it
+ * can deadlock the nfsd threads, due to a LOR. Fortunately
+ * the NFSv4 server always uses SEEK_SET and this code is
+ * only required for the SEEK_END case.
+ */
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
+ VOP_UNLOCK(vp, 0);
+ if (error)
+ return (error);
+ } else
+ vattr.va_size = 0;
return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
}
@@ -420,17 +427,19 @@ int
vop_stdadvlockasync(struct vop_advlockasync_args *ap)
{
struct vnode *vp;
- struct ucred *cred;
struct vattr vattr;
int error;
vp = ap->a_vp;
- cred = curthread->td_ucred;
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_GETATTR(vp, &vattr, cred);
- VOP_UNLOCK(vp, 0);
- if (error)
- return (error);
+ if (ap->a_fl->l_whence == SEEK_END) {
+ /* The size argument is only needed for SEEK_END. */
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
+ VOP_UNLOCK(vp, 0);
+ if (error)
+ return (error);
+ } else
+ vattr.va_size = 0;
return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size));
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 40a69bb..ed4ad4d 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -217,6 +217,8 @@ restart:
return (error);
goto restart;
}
+ if ((vn_open_flags & VN_OPEN_NAMECACHE) != 0)
+ ndp->ni_cnd.cn_flags |= MAKEENTRY;
#ifdef MAC
error = mac_vnode_check_create(cred, ndp->ni_dvp,
&ndp->ni_cnd, vap);
diff --git a/sys/mips/beri/beri_machdep.c b/sys/mips/beri/beri_machdep.c
index 714ee3d..e3cca28 100644
--- a/sys/mips/beri/beri_machdep.c
+++ b/sys/mips/beri/beri_machdep.c
@@ -117,13 +117,13 @@ mips_init(void)
("First region is not within FDT memory range"));
/* Limit size of the first region */
- phys_avail[1] = MIN(mr[0].mr_size, ctob(realmem));
+ phys_avail[1] = (mr[0].mr_start + MIN(mr[0].mr_size, ctob(realmem)));
dump_avail[1] = phys_avail[1];
/* Add the rest of regions */
for (i = 1, j = 2; i < mr_cnt; i++, j+=2) {
phys_avail[j] = mr[i].mr_start;
- phys_avail[j+1] = mr[i].mr_size;
+ phys_avail[j+1] = (mr[i].mr_start + mr[i].mr_size);
dump_avail[j] = phys_avail[j];
dump_avail[j+1] = phys_avail[j+1];
}
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
index a4405ae..98fe812 100644
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -617,7 +617,8 @@ trap(struct trapframe *trapframe)
* XXXDTRACE: add pid probe handler here (if ever)
*/
if (!usermode) {
- if (dtrace_trap_func != NULL && (*dtrace_trap_func)(trapframe))
+ if (dtrace_trap_func != NULL &&
+ (*dtrace_trap_func)(trapframe, type) != 0)
return (trapframe->pc);
}
#endif
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 54533f2..0b1252d 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -248,14 +248,11 @@ SUBDIR= \
netfpga10g \
${_netgraph} \
${_nfe} \
- nfs_common \
nfscl \
- nfsclient \
nfscommon \
nfsd \
nfslock \
nfslockd \
- nfsserver \
nfssvc \
nge \
nmdm \
diff --git a/sys/modules/cryptodev/Makefile b/sys/modules/cryptodev/Makefile
index a82517d..cc5ca12 100644
--- a/sys/modules/cryptodev/Makefile
+++ b/sys/modules/cryptodev/Makefile
@@ -3,6 +3,6 @@
.PATH: ${.CURDIR}/../../opencrypto
KMOD = cryptodev
SRCS = cryptodev.c
-SRCS += bus_if.h device_if.h opt_compat.h
+SRCS += bus_if.h device_if.h opt_compat.h opt_kdtrace.h
.include <bsd.kmod.mk>
diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile
index b84c632..08b6937 100644
--- a/sys/modules/dtrace/Makefile
+++ b/sys/modules/dtrace/Makefile
@@ -4,7 +4,6 @@
SUBDIR= dtmalloc \
dtnfscl \
- dtnfsclient \
dtrace \
dtraceall \
dtrace_test \
diff --git a/sys/modules/dtrace/dtnfsclient/Makefile b/sys/modules/dtrace/dtnfsclient/Makefile
deleted file mode 100644
index 1c5208f..0000000
--- a/sys/modules/dtrace/dtnfsclient/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-SYSDIR?= ${.CURDIR}/../../..
-
-.PATH: ${SYSDIR}/nfsclient
-
-KMOD= dtnfsclient
-SRCS= nfs_kdtrace.c
-SRCS+= vnode_if.h
-
-CFLAGS+= -I${SYSDIR}/cddl/compat/opensolaris \
- -I${SYSDIR}/cddl/contrib/opensolaris/uts/common \
- -I${SYSDIR}
-
-.include <bsd.kmod.mk>
-
-CFLAGS+= -include ${SYSDIR}/cddl/compat/opensolaris/sys/debug_compat.h
diff --git a/sys/modules/dtrace/dtraceall/dtraceall.c b/sys/modules/dtrace/dtraceall/dtraceall.c
index eda740e..c144d06 100644
--- a/sys/modules/dtrace/dtraceall/dtraceall.c
+++ b/sys/modules/dtrace/dtraceall/dtraceall.c
@@ -69,9 +69,6 @@ MODULE_DEPEND(dtraceall, dtmalloc, 1, 1, 1);
#if defined(NFSCLIENT)
MODULE_DEPEND(dtraceall, dtnfscl, 1, 1, 1);
#endif
-#if defined(NFSCLIENT)
-MODULE_DEPEND(dtraceall, dtnfsclient, 1, 1, 1);
-#endif
#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__)
MODULE_DEPEND(dtraceall, fbt, 1, 1, 1);
#endif
diff --git a/sys/modules/geom/geom_sched/gs_sched/Makefile b/sys/modules/geom/geom_sched/gs_sched/Makefile
index 5739365..13bb91b 100644
--- a/sys/modules/geom/geom_sched/gs_sched/Makefile
+++ b/sys/modules/geom/geom_sched/gs_sched/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
KMOD= geom_sched
-SRCS= g_sched.c subr_disk.c
+SRCS= g_sched.c
# ../Makefile.inc automatically included
.include <bsd.kmod.mk>
diff --git a/sys/modules/geom/geom_sched/gsched_rr/Makefile b/sys/modules/geom/geom_sched/gsched_rr/Makefile
index 4209277..44cc566 100644
--- a/sys/modules/geom/geom_sched/gsched_rr/Makefile
+++ b/sys/modules/geom/geom_sched/gsched_rr/Makefile
@@ -2,8 +2,6 @@
KMOD= gsched_rr
SRCS= gs_rr.c
-# hash.h on 6.x has a (char *) cast on a const pointer
-#CWARNFLAGS=
# ../Makefile.inc automatically included
.include <bsd.kmod.mk>
diff --git a/sys/modules/if_gif/Makefile b/sys/modules/if_gif/Makefile
index 663c679..3b3a172 100644
--- a/sys/modules/if_gif/Makefile
+++ b/sys/modules/if_gif/Makefile
@@ -6,7 +6,11 @@ SYSDIR?=${.CURDIR}/../..
.PATH: ${SYSDIR}/net ${SYSDIR}/netinet ${SYSDIR}/netinet6
KMOD= if_gif
-SRCS= if_gif.c in_gif.c opt_inet.h opt_inet6.h
+SRCS= if_gif.c opt_inet.h opt_inet6.h
+
+.if ${MK_INET_SUPPORT} != "no"
+SRCS+= in_gif.c
+.endif
.if ${MK_INET6_SUPPORT} != "no"
SRCS+= in6_gif.c
diff --git a/sys/modules/nfs_common/Makefile b/sys/modules/nfs_common/Makefile
deleted file mode 100644
index 8f51f18..0000000
--- a/sys/modules/nfs_common/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../nfs
-
-KMOD= nfs_common
-SRCS= nfs_common.c opt_nfs.h vnode_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile
deleted file mode 100644
index a015f34..0000000
--- a/sys/modules/nfsclient/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../nfsclient ${.CURDIR}/../../nfs ${.CURDIR}/../../rpc
-
-KMOD= nfsclient
-SRCS= vnode_if.h \
- nfs_bio.c nfs_node.c nfs_subs.c nfs_nfsiod.c \
- nfs_vfsops.c nfs_vnops.c nfs_krpc.c \
- opt_inet.h opt_nfs.h opt_bootp.h opt_nfsroot.h
-SRCS+= opt_inet6.h opt_kgssapi.h
-
-.if !defined(KERNBUILDDIR)
-NFS_ROOT?= 1 # 0/1 - requires NFS_ROOT to be configured in kernel
-
-.if ${NFS_ROOT} > 0
-opt_nfsroot.h:
- echo "#define NFS_ROOT 1" > ${.TARGET}
-.endif
-.else
-OPT_NFS_ROOT!= cat ${KERNBUILDDIR}/opt_nfsroot.h
-.if empty(OPT_NFS_ROOT)
-NFS_ROOT= 0
-.else
-NFS_ROOT= 1
-.endif
-.endif
-
-.if ${NFS_ROOT} > 0
-SRCS+= nfs_diskless.c
-.endif
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/nfsserver/Makefile b/sys/modules/nfsserver/Makefile
deleted file mode 100644
index d00fe47..0000000
--- a/sys/modules/nfsserver/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../nfsserver ${.CURDIR}/../../nfs
-KMOD= nfsserver
-SRCS= vnode_if.h \
- nfs_fha.c nfs_fha_old.c nfs_serv.c nfs_srvkrpc.c nfs_srvsubs.c \
- opt_mac.h \
- opt_kgssapi.h \
- opt_nfs.h
-SRCS+= opt_inet6.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 674060dd..0a4139f 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_ecn.h>
#ifdef INET
#include <netinet/in_var.h>
-#include <netinet/in_gif.h>
#include <netinet/ip_var.h>
#endif /* INET */
@@ -85,7 +84,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_ecn.h>
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
-#include <netinet6/in6_gif.h>
#include <netinet6/ip6protosw.h>
#endif /* INET6 */
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index b5ebf15..b263850 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -114,6 +114,16 @@ void gif_input(struct mbuf *, struct ifnet *, int, uint8_t);
int gif_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
struct route *);
int gif_encapcheck(const struct mbuf *, int, int, void *);
+#ifdef INET
+int in_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
+int in_gif_encapcheck(const struct mbuf *, int, int, void *);
+int in_gif_attach(struct gif_softc *);
+#endif
+#ifdef INET6
+int in6_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
+int in6_gif_encapcheck(const struct mbuf *, int, int, void *);
+int in6_gif_attach(struct gif_softc *);
+#endif
#endif /* _KERNEL */
#define GIFGOPTS _IOWR('i', 150, struct ifreq)
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index 4d00ca2..23e55e2 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -119,16 +119,6 @@ static int gre_set_tunnel(struct ifnet *, struct sockaddr *,
struct sockaddr *);
static void gre_delete_tunnel(struct ifnet *);
-int gre_input(struct mbuf **, int *, int);
-#ifdef INET
-extern int in_gre_attach(struct gre_softc *);
-extern int in_gre_output(struct mbuf *, int, int);
-#endif
-#ifdef INET6
-extern int in6_gre_attach(struct gre_softc *);
-extern int in6_gre_output(struct mbuf *, int, int);
-#endif
-
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
"Generic Routing Encapsulation");
diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h
index 3a48efe..806b0cb 100644
--- a/sys/net/if_gre.h
+++ b/sys/net/if_gre.h
@@ -100,6 +100,15 @@ struct gre_softc {
#define gre_oip gre_gihdr->gi_ip
#define gre_oip6 gre_gi6hdr->gi6_ip6
+int gre_input(struct mbuf **, int *, int);
+#ifdef INET
+int in_gre_attach(struct gre_softc *);
+int in_gre_output(struct mbuf *, int, int);
+#endif
+#ifdef INET6
+int in6_gre_attach(struct gre_softc *);
+int in6_gre_output(struct mbuf *, int, int);
+#endif
/*
* CISCO uses special type for GRE tunnel created as part of WCCP
* connection, while in fact those packets are just IPv4 encapsulated
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index f3a6042..aed2a37 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -99,7 +99,6 @@
#include <net/route.h>
#include <net/netisr.h>
#include <net/if_types.h>
-#include <net/if_stf.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -156,7 +155,8 @@ static MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface");
static const int ip_stf_ttl = 40;
extern struct domain inetdomain;
-struct protosw in_stf_protosw = {
+static int in_stf_input(struct mbuf **, int *, int);
+static struct protosw in_stf_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_IPV6,
@@ -620,7 +620,7 @@ stf_checkaddr6(sc, in6, inifp)
return 0;
}
-int
+static int
in_stf_input(struct mbuf **mp, int *offp, int proto)
{
struct stf_softc *sc;
diff --git a/sys/net/if_stf.h b/sys/net/if_stf.h
deleted file mode 100644
index 07f585b..0000000
--- a/sys/net/if_stf.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: if_stf.h,v 1.5 2001/10/12 10:09:17 keiichi Exp $ */
-
-/*-
- * Copyright (C) 2000 WIDE Project.
- * 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.
- * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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 _NET_IF_STF_H_
-#define _NET_IF_STF_H_
-
-int in_stf_input(struct mbuf **, int *, int);
-
-#endif /* _NET_IF_STF_H_ */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index a8d92f9..8cb1f51 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1702,7 +1702,7 @@ ieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs)
/*
* Add an ssid element to a frame.
*/
-static uint8_t *
+uint8_t *
ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len)
{
*frm++ = IEEE80211_ELEMID_SSID;
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 04b3c3a..812cd70 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -560,10 +560,15 @@ ieee80211_sta_pwrsave(struct ieee80211vap *vap, int enable)
* Handle being notified that we have data available for us in a TIM/ATIM.
*
* This may schedule a transition from _SLEEP -> _RUN if it's appropriate.
+ *
+ * In STA mode, we may have put to sleep during scan and need to be dragged
+ * back out of powersave mode.
*/
void
ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set)
{
+ struct ieee80211com *ic = vap->iv_ic;
+
/*
* Schedule the driver state change. It'll happen at some point soon.
* Since the hardware shouldn't know that we're running just yet
@@ -574,10 +579,24 @@ ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set)
* XXX TODO: verify that the transition to RUN will wake up the
* BSS node!
*/
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: TIM=%d\n", __func__, set);
IEEE80211_LOCK(vap->iv_ic);
if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) {
ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0);
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: TIM=%d; wakeup\n", __func__, set);
+ } else if ((set == 1) && (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)) {
+ /*
+ * XXX only do this if we're in RUN state?
+ */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER,
+ "%s: wake up from bgscan vap sleep\n",
+ __func__);
+ /*
+ * We may be in BGSCAN mode - this means the VAP is is in STA
+ * mode powersave. If it is, we need to wake it up so we
+ * can process outbound traffic.
+ */
+ vap->iv_sta_ps(vap, 0);
}
IEEE80211_UNLOCK(vap->iv_ic);
}
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index 8df5116..3b46ac4 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -149,6 +149,7 @@ struct mbuf *ieee80211_alloc_cts(struct ieee80211com *,
uint8_t *ieee80211_add_rates(uint8_t *, const struct ieee80211_rateset *);
uint8_t *ieee80211_add_xrates(uint8_t *, const struct ieee80211_rateset *);
+uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int);
uint8_t *ieee80211_add_wpa(uint8_t *, const struct ieee80211vap *);
uint8_t *ieee80211_add_rsn(uint8_t *, const struct ieee80211vap *);
uint8_t *ieee80211_add_qos(uint8_t *, const struct ieee80211_node *);
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index 66e8430..d81ba7c 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -698,6 +698,13 @@ ieee80211_cancel_scan(struct ieee80211vap *vap)
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
/* wake up the scan task */
scan_signal(ss);
+ } else {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
+ __func__,
+ !! (ic->ic_flags & IEEE80211_F_SCAN),
+ (ss->ss_vap == vap ? "match" : "nomatch"),
+ !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
}
IEEE80211_UNLOCK(ic);
}
@@ -724,6 +731,13 @@ ieee80211_cancel_anyscan(struct ieee80211vap *vap)
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
/* wake up the scan task */
scan_signal(ss);
+ } else {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
+ __func__,
+ !! (ic->ic_flags & IEEE80211_F_SCAN),
+ (ss->ss_vap == vap ? "match" : "nomatch"),
+ !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
}
IEEE80211_UNLOCK(ic);
}
@@ -738,6 +752,8 @@ ieee80211_scan_next(struct ieee80211vap *vap)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
/* wake up the scan task */
IEEE80211_LOCK(ic);
scan_signal(ss);
@@ -754,6 +770,8 @@ ieee80211_scan_done(struct ieee80211vap *vap)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_state *ss;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
IEEE80211_LOCK(ic);
ss = ic->ic_scan;
ss->ss_next = ss->ss_last; /* all channels are complete */
@@ -807,6 +825,10 @@ scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: calling; maxdwell=%lu\n",
+ __func__,
+ maxdwell);
IEEE80211_LOCK(vap->iv_ic);
if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
ieee80211_probe_curchan(vap, 0);
@@ -821,7 +843,6 @@ scan_signal(void *arg)
struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
IEEE80211_LOCK_ASSERT(ss->ss_ic);
-
cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv);
}
@@ -834,6 +855,8 @@ scan_mindwell(struct ieee80211_scan_state *ss)
{
struct ieee80211com *ic = ss->ss_ic;
+ IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
+
IEEE80211_LOCK(ic);
scan_signal(ss);
IEEE80211_UNLOCK(ic);
@@ -882,13 +905,23 @@ scan_task(void *arg, int pending)
}
scanend = ticks + SCAN_PRIVATE(ss)->ss_duration;
+
+ /* XXX scan state can change! Re-validate scan state! */
+
IEEE80211_UNLOCK(ic);
ic->ic_scan_start(ic); /* notify driver */
IEEE80211_LOCK(ic);
for (;;) {
+
scandone = (ss->ss_next >= ss->ss_last) ||
(SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: loop start; scandone=%d\n",
+ __func__,
+ scandone);
+
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
(SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
time_after(ticks + ss->ss_mindwell, scanend))
@@ -944,6 +977,8 @@ scan_task(void *arg, int pending)
ic->ic_scan_curchan(ss, maxdwell);
IEEE80211_LOCK(ic);
+ /* XXX scan state can change! Re-validate scan state! */
+
SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
/* clear mindwell lock and initial channel change flush */
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
@@ -951,15 +986,20 @@ scan_task(void *arg, int pending)
if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
continue;
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__);
/* Wait to be signalled to scan the next channel */
cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
}
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__);
+
if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
goto done;
IEEE80211_UNLOCK(ic);
ic->ic_scan_end(ic); /* notify driver */
IEEE80211_LOCK(ic);
+ /* XXX scan state can change! Re-validate scan state! */
/*
* Since a cancellation may have occured during one of the
@@ -969,10 +1009,10 @@ scan_task(void *arg, int pending)
((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
/* XXX printf? */
if_printf(vap->iv_ifp,
- "%s: OOPS! scan cancelled during driver call!\n",
+ "%s: OOPS! scan cancelled during driver call (1)!\n",
__func__);
+ scandone = 1;
}
- scandone |= ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0);
/*
* Record scan complete time. Note that we also do
@@ -1032,6 +1072,19 @@ scan_task(void *arg, int pending)
ticks, ss->ss_mindwell, scanend);
/*
+ * Since a cancellation may have occured during one of the
+ * driver calls (whilst unlocked), update scandone.
+ */
+ if (scandone == 0 &&
+ ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
+ /* XXX printf? */
+ if_printf(vap->iv_ifp,
+ "%s: OOPS! scan cancelled during driver call (2)!\n",
+ __func__);
+ scandone = 1;
+ }
+
+ /*
* Clear the SCAN bit first in case frames are
* pending on the station power save queue. If
* we defer this then the dispatch of the frames
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 89ed856..c3c2bc9 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -1405,6 +1405,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
int ix = aid / NBBY;
int min = tim->tim_bitctl &~ 1;
int max = tim->tim_len + min - 4;
+ int tim_ucast = 0, tim_mcast = 0;
/*
* Only do this for unicast traffic in the TIM
@@ -1414,20 +1415,42 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
*/
if (min <= ix && ix <= max &&
isset(tim->tim_bitmap - min, aid)) {
- ieee80211_sta_tim_notify(vap, 1);
- ic->ic_lastdata = ticks;
+ tim_ucast = 1;
}
/*
- * XXX TODO: do a separate notification
+ * Do a separate notification
* for the multicast bit being set.
*/
-#if 0
if (tim->tim_bitctl & 1) {
+ tim_mcast = 1;
+ }
+
+ /*
+ * If the TIM indicates there's traffic for
+ * us then get us out of STA mode powersave.
+ */
+ if (tim_ucast == 1) {
+
+ /*
+ * Wake us out of SLEEP state if we're
+ * in it; and if we're doing bgscan
+ * then wake us out of STA powersave.
+ */
ieee80211_sta_tim_notify(vap, 1);
+
+ /*
+ * This is preventing us from
+ * continuing a bgscan; because it
+ * tricks the contbgscan()
+ * routine to think there's always
+ * traffic for us.
+ *
+ * I think we need both an RX and
+ * TX ic_lastdata field.
+ */
ic->ic_lastdata = ticks;
}
-#endif
ni->ni_dtim_count = tim->tim_count;
ni->ni_dtim_period = tim->tim_period;
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 46f68f5..cd412ad 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
-#include <netinet/in_gif.h>
#include <netinet/in_var.h>
#include <netinet/ip_encap.h>
#include <netinet/ip_ecn.h>
@@ -70,9 +69,10 @@ __FBSDID("$FreeBSD$");
static int gif_validate4(const struct ip *, struct gif_softc *,
struct ifnet *);
+static int in_gif_input(struct mbuf **, int *, int);
extern struct domain inetdomain;
-struct protosw in_gif_protosw = {
+static struct protosw in_gif_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
.pr_protocol = 0/* IPPROTO_IPV[46] */,
@@ -83,7 +83,8 @@ struct protosw in_gif_protosw = {
.pr_usrreqs = &rip_usrreqs
};
-VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
+#define GIF_TTL 30
+static VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
#define V_ip_gif_ttl VNET(ip_gif_ttl)
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ip_gif_ttl), 0, "");
@@ -133,7 +134,7 @@ in_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
return (ip_output(m, NULL, NULL, 0, NULL, NULL));
}
-int
+static int
in_gif_input(struct mbuf **mp, int *offp, int proto)
{
struct mbuf *m = *mp;
diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h
deleted file mode 100644
index d48d881..0000000
--- a/sys/netinet/in_gif.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* $FreeBSD$ */
-/* $KAME: in_gif.h,v 1.5 2000/04/14 08:36:02 itojun Exp $ */
-
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * 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.
- * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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 _NETINET_IN_GIF_H_
-#define _NETINET_IN_GIF_H_
-
-#define GIF_TTL 30
-
-struct gif_softc;
-int in_gif_input(struct mbuf **, int *, int);
-int in_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
-int in_gif_encapcheck(const struct mbuf *, int, int, void *);
-int in_gif_attach(struct gif_softc *);
-
-#endif /*_NETINET_IN_GIF_H_*/
diff --git a/sys/netinet/in_systm.h b/sys/netinet/in_systm.h
index 4b34aa0..acd2e62 100644
--- a/sys/netinet/in_systm.h
+++ b/sys/netinet/in_systm.h
@@ -44,12 +44,15 @@
* Internally the system keeps counters in the headers with the bytes
* swapped so that VAX instructions will work on them. It reverses
* the bytes before transmission at each protocol level. The n_ types
- * represent the types with the bytes in ``high-ender'' order.
+ * represent the types with the bytes in ``high-ender'' order. Network
+ * byte order is usually referered to as big-endian these days rather
+ * than high-ender, which sadly invokes an Orson Scott Card novel, or
+ * worse, the movie.
*/
typedef u_int16_t n_short; /* short as received from the net */
typedef u_int32_t n_long; /* long as received from the net */
-typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */
+typedef u_int32_t n_time; /* ms since 00:00 UTC, byte rev */
#ifdef _KERNEL
uint32_t iptime(void);
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c
index 9f28191..5942364 100644
--- a/sys/netinet/ip_gre.c
+++ b/sys/netinet/ip_gre.c
@@ -68,11 +68,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_gre.h>
extern struct domain inetdomain;
-extern int gre_input(struct mbuf **, int *, int);
-
-int in_gre_attach(struct gre_softc *);
-int in_gre_output(struct mbuf *, int, int);
-
static const struct protosw in_gre_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index d134a2e..b6b967f 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -861,7 +861,7 @@ icmp_send(struct mbuf *m, struct mbuf *opts)
}
/*
- * Return milliseconds since 00:00 GMT in network format.
+ * Return milliseconds since 00:00 UTC in network format.
*/
uint32_t
iptime(void)
diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h
index ca1e963..38d44d7 100644
--- a/sys/netinet/ip_icmp.h
+++ b/sys/netinet/ip_icmp.h
@@ -99,7 +99,7 @@ struct icmp {
struct id_ts { /* ICMP Timestamp */
/*
* The next 3 fields are in network format,
- * milliseconds since 00:00 GMT
+ * milliseconds since 00:00 UTC
*/
uint32_t its_otime; /* Originate */
uint32_t its_rtime; /* Receive */
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 617e480..95955de 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -3639,16 +3639,10 @@ flags_out:
policy = sprstat->sprstat_policy;
#if defined(SCTP_DETAILED_STR_STATS)
if ((stcb != NULL) &&
- (policy != SCTP_PR_SCTP_NONE) &&
(sid < stcb->asoc.streamoutcnt) &&
- ((policy == SCTP_PR_SCTP_ALL) ||
- (PR_SCTP_VALID_POLICY(policy)))) {
-#else
- if ((stcb != NULL) &&
(policy != SCTP_PR_SCTP_NONE) &&
- (sid < stcb->asoc.streamoutcnt) &&
- (policy == SCTP_PR_SCTP_ALL)) {
-#endif
+ ((policy <= SCTP_PR_SCTP_MAX) ||
+ (policy == SCTP_PR_SCTP_ALL))) {
if (policy == SCTP_PR_SCTP_ALL) {
sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
@@ -3656,6 +3650,13 @@ flags_out:
sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
}
+#else
+ if ((stcb != NULL) &&
+ (sid < stcb->asoc.streamoutcnt) &&
+ (policy == SCTP_PR_SCTP_ALL)) {
+ sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
+ sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
+#endif
SCTP_TCB_UNLOCK(stcb);
*optsize = sizeof(struct sctp_prstatus);
} else {
@@ -3675,8 +3676,8 @@ flags_out:
policy = sprstat->sprstat_policy;
if ((stcb != NULL) &&
(policy != SCTP_PR_SCTP_NONE) &&
- ((policy == SCTP_PR_SCTP_ALL) ||
- (PR_SCTP_VALID_POLICY(policy)))) {
+ ((policy <= SCTP_PR_SCTP_MAX) ||
+ (policy == SCTP_PR_SCTP_ALL))) {
if (policy == SCTP_PR_SCTP_ALL) {
sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
@@ -6037,7 +6038,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
- if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
+ if (info->pr_policy > SCTP_PR_SCTP_MAX) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
break;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index d066c74..edf6ae8 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1949,7 +1949,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* though we use a different timer. We also add the HB timer
* PLUS a random jitter.
*/
- if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
+ if ((stcb == NULL) || (net == NULL)) {
return;
} else {
uint32_t rndval;
@@ -2004,9 +2004,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* nothing needed but the endpoint here ususually about 60
* minutes.
*/
- if (inp == NULL) {
- return;
- }
tmr = &inp->sctp_ep.signature_change;
to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
break;
@@ -2023,9 +2020,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* timer since that has stopped and we are in the GONE
* state.
*/
- if (inp == NULL) {
- return;
- }
tmr = &inp->sctp_ep.signature_change;
to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT);
break;
@@ -2034,10 +2028,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* Here we use the value found in the EP for PMTU ususually
* about 10 minutes.
*/
- if ((stcb == NULL) || (inp == NULL)) {
- return;
- }
- if (net == NULL) {
+ if ((stcb == NULL) || (net == NULL)) {
return;
}
if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
@@ -2063,7 +2054,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* Here we use the endpoints shutdown guard timer usually
* about 3 minutes.
*/
- if ((inp == NULL) || (stcb == NULL)) {
+ if (stcb == NULL) {
return;
}
to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index 10d5d7b..3db4b4f 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
-#include <netinet6/in6_gif.h>
#include <netinet6/in6_var.h>
#endif
#include <netinet/ip_ecn.h>
@@ -74,7 +73,8 @@ __FBSDID("$FreeBSD$");
#include <net/if_gif.h>
-VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
+#define GIF_HLIM 30
+static VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
SYSCTL_DECL(_net_inet6_ip6);
@@ -83,9 +83,10 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_VNET | CTLFLAG_RW,
static int gif_validate6(const struct ip6_hdr *, struct gif_softc *,
struct ifnet *);
+static int in6_gif_input(struct mbuf **, int *, int);
extern struct domain inet6domain;
-struct protosw in6_gif_protosw = {
+static struct protosw in6_gif_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = 0, /* IPPROTO_IPV[46] */
@@ -144,7 +145,7 @@ in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn)
return (ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL, NULL));
}
-int
+static int
in6_gif_input(struct mbuf **mp, int *offp, int proto)
{
struct mbuf *m = *mp;
diff --git a/sys/netinet6/in6_gif.h b/sys/netinet6/in6_gif.h
deleted file mode 100644
index 1246171..0000000
--- a/sys/netinet6/in6_gif.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * 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.
- * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
- *
- * $KAME: in6_gif.h,v 1.5 2000/04/14 08:36:03 itojun Exp $
- * $FreeBSD$
- */
-
-#ifndef _NETINET6_IN6_GIF_H_
-#define _NETINET6_IN6_GIF_H_
-
-#define GIF_HLIM 30
-
-struct gif_softc;
-int in6_gif_input(struct mbuf **, int *, int);
-int in6_gif_output(struct ifnet *, struct mbuf *, int, uint8_t);
-int in6_gif_encapcheck(const struct mbuf *, int, int, void *);
-int in6_gif_attach(struct gif_softc *);
-
-#endif /* _NETINET6_IN6_GIF_H_ */
diff --git a/sys/netinet6/ip6_gre.c b/sys/netinet6/ip6_gre.c
index 29a0725..095a1de 100644
--- a/sys/netinet6/ip6_gre.c
+++ b/sys/netinet6/ip6_gre.c
@@ -62,11 +62,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_gre.h>
extern struct domain inet6domain;
-extern int gre_input(struct mbuf **, int *, int);
-
-int in6_gre_attach(struct gre_softc *);
-int in6_gre_output(struct mbuf *, int, int);
-
struct protosw in6_gre_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 5e0cdbf..8a79052 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -118,11 +118,12 @@ VNET_DEFINE(int, ip4_esp_trans_deflev) = IPSEC_LEVEL_USE;
VNET_DEFINE(int, ip4_esp_net_deflev) = IPSEC_LEVEL_USE;
VNET_DEFINE(int, ip4_ah_trans_deflev) = IPSEC_LEVEL_USE;
VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE;
-VNET_DEFINE(struct secpolicy, ip4_def_policy);
/* ECN ignore(-1)/forbidden(0)/allowed(1) */
VNET_DEFINE(int, ip4_ipsec_ecn) = 0;
VNET_DEFINE(int, ip4_esp_randpad) = -1;
+static VNET_DEFINE(struct secpolicy, def_policy);
+#define V_def_policy VNET(def_policy)
/*
* Crypto support requirements:
*
@@ -141,7 +142,7 @@ SYSCTL_DECL(_net_inet_ipsec);
/* net.inet.ipsec */
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_def_policy).policy, 0,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0,
"IPsec default policy.");
SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0,
@@ -213,7 +214,7 @@ SYSCTL_DECL(_net_inet6_ipsec6);
/* net.inet6.ipsec6 */
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy,
- CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_def_policy).policy, 0,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(def_policy).policy, 0,
"IPsec default policy.");
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0,
@@ -262,7 +263,7 @@ key_allocsp_default(const char* where, int tag)
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP key_allocsp_default from %s:%u\n", where, tag));
- sp = &V_ip4_def_policy;
+ sp = &V_def_policy;
if (sp->policy != IPSEC_POLICY_DISCARD &&
sp->policy != IPSEC_POLICY_NONE) {
ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
@@ -828,17 +829,13 @@ ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp)
ipsec_delpcbpolicy(new);
return (ENOBUFS);
}
- new->sp_in->state = IPSEC_SPSTATE_ALIVE;
new->sp_in->policy = IPSEC_POLICY_ENTRUST;
-
if ((new->sp_out = KEY_NEWSP()) == NULL) {
KEY_FREESP(&new->sp_in);
ipsec_delpcbpolicy(new);
return (ENOBUFS);
}
- new->sp_out->state = IPSEC_SPSTATE_ALIVE;
new->sp_out->policy = IPSEC_POLICY_ENTRUST;
-
*pcb_sp = new;
return (0);
@@ -927,7 +924,6 @@ ipsec_deepcopy_policy(struct secpolicy *src)
}
dst->req = newchain;
- dst->state = src->state;
dst->policy = src->policy;
/* Do not touch the refcnt fields. */
@@ -979,8 +975,6 @@ ipsec_set_policy_internal(struct secpolicy **pcb_sp, int optname,
if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
return (error);
- newsp->state = IPSEC_SPSTATE_ALIVE;
-
/* Clear old SP and set new SP. */
KEY_FREESP(pcb_sp);
*pcb_sp = newsp;
@@ -1693,14 +1687,15 @@ ipsec_dumpmbuf(struct mbuf *m)
}
static void
-ipsec_init(const void *unused __unused)
+def_policy_init(const void *unused __unused)
{
- SECPOLICY_LOCK_INIT(&V_ip4_def_policy);
- V_ip4_def_policy.refcnt = 1; /* NB: disallow free. */
+ bzero(&V_def_policy, sizeof(struct secpolicy));
+ V_def_policy.policy = IPSEC_POLICY_NONE;
+ V_def_policy.refcnt = 1;
}
-VNET_SYSINIT(ipsec_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY, ipsec_init,
- NULL);
+VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAININIT, SI_ORDER_ANY,
+ def_policy_init, NULL);
/* XXX This stuff doesn't belong here... */
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 8ed39fb..5e3e1c3 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -81,21 +81,15 @@ struct secpolicyindex {
/* Security Policy Data Base */
struct secpolicy {
- LIST_ENTRY(secpolicy) chain;
- struct mtx lock;
+ TAILQ_ENTRY(secpolicy) chain;
- u_int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
- u_int32_t id; /* It's unique number on the system. */
- u_int state; /* 0: dead, others: alive */
-#define IPSEC_SPSTATE_DEAD 0
-#define IPSEC_SPSTATE_ALIVE 1
- u_int policy; /* policy_type per pfkeyv2.h */
- u_int16_t scangen; /* scan generation # */
struct ipsecrequest *req;
/* pointer to the ipsec request tree, */
/* if policy == IPSEC else this value == NULL.*/
-
+ u_int refcnt; /* reference count */
+ u_int policy; /* policy_type per pfkeyv2.h */
+ u_int32_t id; /* It's unique number on the system. */
/*
* lifetime handler.
* the policy can be used without limitiation if both lifetime and
@@ -109,13 +103,6 @@ struct secpolicy {
long validtime; /* duration this policy is valid without use */
};
-#define SECPOLICY_LOCK_INIT(_sp) \
- mtx_init(&(_sp)->lock, "ipsec policy", NULL, MTX_DEF)
-#define SECPOLICY_LOCK(_sp) mtx_lock(&(_sp)->lock)
-#define SECPOLICY_UNLOCK(_sp) mtx_unlock(&(_sp)->lock)
-#define SECPOLICY_LOCK_DESTROY(_sp) mtx_destroy(&(_sp)->lock)
-#define SECPOLICY_LOCK_ASSERT(_sp) mtx_assert(&(_sp)->lock, MA_OWNED)
-
/* Request for IPsec */
struct ipsecrequest {
struct ipsecrequest *next;
@@ -279,7 +266,6 @@ VNET_DECLARE(int, ipsec_integrity);
#endif
VNET_PCPUSTAT_DECLARE(struct ipsecstat, ipsec4stat);
-VNET_DECLARE(struct secpolicy, ip4_def_policy);
VNET_DECLARE(int, ip4_esp_trans_deflev);
VNET_DECLARE(int, ip4_esp_net_deflev);
VNET_DECLARE(int, ip4_ah_trans_deflev);
@@ -292,7 +278,6 @@ VNET_DECLARE(int, crypto_support);
#define IPSECSTAT_INC(name) \
VNET_PCPUSTAT_ADD(struct ipsecstat, ipsec4stat, name, 1)
-#define V_ip4_def_policy VNET(ip4_def_policy)
#define V_ip4_esp_trans_deflev VNET(ip4_esp_trans_deflev)
#define V_ip4_esp_net_deflev VNET(ip4_esp_net_deflev)
#define V_ip4_ah_trans_deflev VNET(ip4_ah_trans_deflev)
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 953f453..b9bcd59 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -48,6 +48,7 @@
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/malloc.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -141,16 +142,19 @@ static VNET_DEFINE(u_int32_t, acq_seq) = 0;
#define V_acq_seq VNET(acq_seq)
/* SPD */
-static VNET_DEFINE(LIST_HEAD(_sptree, secpolicy), sptree[IPSEC_DIR_MAX]);
+static VNET_DEFINE(TAILQ_HEAD(_sptree, secpolicy), sptree[IPSEC_DIR_MAX]);
+static struct rmlock sptree_lock;
#define V_sptree VNET(sptree)
-static struct mtx sptree_lock;
-#define SPTREE_LOCK_INIT() \
- mtx_init(&sptree_lock, "sptree", \
- "fast ipsec security policy database", MTX_DEF)
-#define SPTREE_LOCK_DESTROY() mtx_destroy(&sptree_lock)
-#define SPTREE_LOCK() mtx_lock(&sptree_lock)
-#define SPTREE_UNLOCK() mtx_unlock(&sptree_lock)
-#define SPTREE_LOCK_ASSERT() mtx_assert(&sptree_lock, MA_OWNED)
+#define SPTREE_LOCK_INIT() rm_init(&sptree_lock, "sptree")
+#define SPTREE_LOCK_DESTROY() rm_destroy(&sptree_lock)
+#define SPTREE_RLOCK_TRACKER struct rm_priotracker sptree_tracker
+#define SPTREE_RLOCK() rm_rlock(&sptree_lock, &sptree_tracker)
+#define SPTREE_RUNLOCK() rm_runlock(&sptree_lock, &sptree_tracker)
+#define SPTREE_RLOCK_ASSERT() rm_assert(&sptree_lock, RA_RLOCKED)
+#define SPTREE_WLOCK() rm_wlock(&sptree_lock)
+#define SPTREE_WUNLOCK() rm_wunlock(&sptree_lock)
+#define SPTREE_WLOCK_ASSERT() rm_assert(&sptree_lock, RA_WLOCKED)
+#define SPTREE_UNLOCK_ASSERT() rm_assert(&sptree_lock, RA_UNLOCKED)
static VNET_DEFINE(LIST_HEAD(_sahtree, secashead), sahtree); /* SAD */
#define V_sahtree VNET(sahtree)
@@ -416,9 +420,8 @@ static struct callout key_timer;
static struct secasvar *key_allocsa_policy(const struct secasindex *);
static void key_freesp_so(struct secpolicy **);
static struct secasvar *key_do_allocsa_policy(struct secashead *, u_int);
-static void key_delsp(struct secpolicy *);
+static void key_unlink(struct secpolicy *);
static struct secpolicy *key_getsp(struct secpolicyindex *);
-static void _key_delsp(struct secpolicy *sp);
static struct secpolicy *key_getspbyid(u_int32_t);
static u_int32_t key_newreqid(void);
static struct mbuf *key_gather_mbuf(struct mbuf *,
@@ -575,15 +578,8 @@ sa_delref(struct secasvar *sav)
return (refcount_release(&sav->refcnt));
}
-#define SP_ADDREF(p) do { \
- (p)->refcnt++; \
- IPSEC_ASSERT((p)->refcnt != 0, ("SP refcnt overflow")); \
-} while (0)
-#define SP_DELREF(p) do { \
- IPSEC_ASSERT((p)->refcnt > 0, ("SP refcnt underflow")); \
- (p)->refcnt--; \
-} while (0)
-
+#define SP_ADDREF(p) refcount_acquire(&(p)->refcnt)
+#define SP_DELREF(p) refcount_release(&(p)->refcnt)
/*
* Update the refcnt while holding the SPTREE lock.
@@ -591,9 +587,8 @@ sa_delref(struct secasvar *sav)
void
key_addref(struct secpolicy *sp)
{
- SPTREE_LOCK();
+
SP_ADDREF(sp);
- SPTREE_UNLOCK();
}
/*
@@ -606,7 +601,7 @@ key_havesp(u_int dir)
{
return (dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND ?
- LIST_FIRST(&V_sptree[dir]) != NULL : 1);
+ TAILQ_FIRST(&V_sptree[dir]) != NULL : 1);
}
/* %%% IPsec policy management */
@@ -620,6 +615,7 @@ struct secpolicy *
key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where,
int tag)
{
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
IPSEC_ASSERT(spidx != NULL, ("null spidx"));
@@ -634,14 +630,11 @@ key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where,
printf("*** objects\n");
kdebug_secpolicyindex(spidx));
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[dir], chain) {
+ SPTREE_RLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
kdebug_secpolicyindex(&sp->spidx));
-
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
if (key_cmpspidx_withmask(&sp->spidx, spidx))
goto found;
}
@@ -655,7 +648,7 @@ found:
sp->lastused = time_second;
SP_ADDREF(sp);
}
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
@@ -673,6 +666,7 @@ struct secpolicy *
key_allocsp2(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto,
u_int dir, const char* where, int tag)
{
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
IPSEC_ASSERT(dst != NULL, ("null dst"));
@@ -688,14 +682,11 @@ key_allocsp2(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto,
printf("spi %u proto %u dir %u\n", spi, proto, dir);
kdebug_sockaddr(&dst->sa));
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[dir], chain) {
+ SPTREE_RLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
kdebug_secpolicyindex(&sp->spidx));
-
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
/* compare simple values, then dst address */
if (sp->spidx.ul_proto != proto)
continue;
@@ -715,7 +706,7 @@ found:
sp->lastused = time_second;
SP_ADDREF(sp);
}
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
@@ -1174,22 +1165,41 @@ done:
void
_key_freesp(struct secpolicy **spp, const char* where, int tag)
{
+ struct ipsecrequest *isr, *nextisr;
struct secpolicy *sp = *spp;
IPSEC_ASSERT(sp != NULL, ("null sp"));
-
- SPTREE_LOCK();
- SP_DELREF(sp);
-
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s SP:%p (ID=%u) from %s:%u; refcnt now %u\n",
__func__, sp, sp->id, where, tag, sp->refcnt));
- if (sp->refcnt == 0) {
- *spp = NULL;
- key_delsp(sp);
+ if (SP_DELREF(sp) == 0)
+ return;
+ *spp = NULL;
+ for (isr = sp->req; isr != NULL; isr = nextisr) {
+ if (isr->sav != NULL) {
+ KEY_FREESAV(&isr->sav);
+ isr->sav = NULL;
+ }
+ nextisr = isr->next;
+ ipsec_delisr(isr);
}
- SPTREE_UNLOCK();
+ free(sp, M_IPSEC_SP);
+}
+
+static void
+key_unlink(struct secpolicy *sp)
+{
+
+ IPSEC_ASSERT(sp != NULL, ("null sp"));
+ IPSEC_ASSERT(sp->spidx.dir == IPSEC_DIR_INBOUND ||
+ sp->spidx.dir == IPSEC_DIR_OUTBOUND,
+ ("invalid direction %u", sp->spidx.dir));
+ SPTREE_UNLOCK_ASSERT();
+
+ SPTREE_WLOCK();
+ TAILQ_REMOVE(&V_sptree[sp->spidx.dir], sp, chain);
+ SPTREE_WUNLOCK();
}
/*
@@ -1278,38 +1288,6 @@ key_freesav(struct secasvar **psav, const char* where, int tag)
/* %%% SPD management */
/*
- * free security policy entry.
- */
-static void
-key_delsp(struct secpolicy *sp)
-{
- struct ipsecrequest *isr, *nextisr;
-
- IPSEC_ASSERT(sp != NULL, ("null sp"));
- SPTREE_LOCK_ASSERT();
-
- sp->state = IPSEC_SPSTATE_DEAD;
-
- IPSEC_ASSERT(sp->refcnt == 0,
- ("SP with references deleted (refcnt %u)", sp->refcnt));
-
- /* remove from SP index */
- if (__LIST_CHAINED(sp))
- LIST_REMOVE(sp, chain);
-
- for (isr = sp->req; isr != NULL; isr = nextisr) {
- if (isr->sav != NULL) {
- KEY_FREESAV(&isr->sav);
- isr->sav = NULL;
- }
-
- nextisr = isr->next;
- ipsec_delisr(isr);
- }
- _key_delsp(sp);
-}
-
-/*
* search SPD
* OUT: NULL : not found
* others : found, pointer to a SP.
@@ -1317,20 +1295,19 @@ key_delsp(struct secpolicy *sp)
static struct secpolicy *
key_getsp(struct secpolicyindex *spidx)
{
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
IPSEC_ASSERT(spidx != NULL, ("null spidx"));
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[spidx->dir], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
+ SPTREE_RLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[spidx->dir], chain) {
if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
SP_ADDREF(sp);
break;
}
}
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
return sp;
}
@@ -1343,28 +1320,25 @@ key_getsp(struct secpolicyindex *spidx)
static struct secpolicy *
key_getspbyid(u_int32_t id)
{
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[IPSEC_DIR_INBOUND], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
+ SPTREE_RLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[IPSEC_DIR_INBOUND], chain) {
if (sp->id == id) {
SP_ADDREF(sp);
goto done;
}
}
- LIST_FOREACH(sp, &V_sptree[IPSEC_DIR_OUTBOUND], chain) {
- if (sp->state == IPSEC_SPSTATE_DEAD)
- continue;
+ TAILQ_FOREACH(sp, &V_sptree[IPSEC_DIR_OUTBOUND], chain) {
if (sp->id == id) {
SP_ADDREF(sp);
goto done;
}
}
done:
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
return sp;
}
@@ -1376,11 +1350,8 @@ key_newsp(const char* where, int tag)
newsp = (struct secpolicy *)
malloc(sizeof(struct secpolicy), M_IPSEC_SP, M_NOWAIT|M_ZERO);
- if (newsp) {
- SECPOLICY_LOCK_INIT(newsp);
- newsp->refcnt = 1;
- newsp->req = NULL;
- }
+ if (newsp)
+ refcount_init(&newsp->refcnt, 1);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s from %s:%u return SP:%p\n", __func__,
@@ -1388,13 +1359,6 @@ key_newsp(const char* where, int tag)
return newsp;
}
-static void
-_key_delsp(struct secpolicy *sp)
-{
- SECPOLICY_LOCK_DESTROY(sp);
- free(sp, M_IPSEC_SP);
-}
-
/*
* create secpolicy structure from sadb_x_policy structure.
* NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
@@ -1874,9 +1838,7 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
newsp = key_getsp(&spidx);
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
if (newsp) {
- SPTREE_LOCK();
- newsp->state = IPSEC_SPSTATE_DEAD;
- SPTREE_UNLOCK();
+ key_unlink(newsp);
KEY_FREESP(&newsp);
}
} else {
@@ -1888,13 +1850,15 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
}
}
+ /* XXX: there is race between key_getsp and key_msg2sp. */
+
/* allocation new SP entry */
if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) {
return key_senderror(so, m, error);
}
if ((newsp->id = key_getnewspid()) == 0) {
- _key_delsp(newsp);
+ KEY_FREESP(&newsp);
return key_senderror(so, m, ENOBUFS);
}
@@ -1910,18 +1874,20 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
/* sanity check on addr pair */
if (((struct sockaddr *)(src0 + 1))->sa_family !=
((struct sockaddr *)(dst0+ 1))->sa_family) {
- _key_delsp(newsp);
+ KEY_FREESP(&newsp);
return key_senderror(so, m, EINVAL);
}
if (((struct sockaddr *)(src0 + 1))->sa_len !=
((struct sockaddr *)(dst0+ 1))->sa_len) {
- _key_delsp(newsp);
+ KEY_FREESP(&newsp);
return key_senderror(so, m, EINVAL);
}
#if 1
- if (newsp->req && newsp->req->saidx.src.sa.sa_family && newsp->req->saidx.dst.sa.sa_family) {
- if (newsp->req->saidx.src.sa.sa_family != newsp->req->saidx.dst.sa.sa_family) {
- _key_delsp(newsp);
+ if (newsp->req && newsp->req->saidx.src.sa.sa_family &&
+ newsp->req->saidx.dst.sa.sa_family) {
+ if (newsp->req->saidx.src.sa.sa_family !=
+ newsp->req->saidx.dst.sa.sa_family) {
+ KEY_FREESP(&newsp);
return key_senderror(so, m, EINVAL);
}
}
@@ -1932,9 +1898,9 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0;
newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0;
- newsp->refcnt = 1; /* do not reclaim until I say I do */
- newsp->state = IPSEC_SPSTATE_ALIVE;
- LIST_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, secpolicy, chain);
+ SPTREE_WLOCK();
+ TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain);
+ SPTREE_WUNLOCK();
/* delete the entry in spacqtree */
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
@@ -2109,9 +2075,7 @@ key_spddelete(struct socket *so, struct mbuf *m,
/* save policy id to buffer to be returned. */
xpl0->sadb_x_policy_id = sp->id;
- SPTREE_LOCK();
- sp->state = IPSEC_SPSTATE_DEAD;
- SPTREE_UNLOCK();
+ key_unlink(sp);
KEY_FREESP(&sp);
{
@@ -2176,9 +2140,7 @@ key_spddelete2(struct socket *so, struct mbuf *m,
return key_senderror(so, m, EINVAL);
}
- SPTREE_LOCK();
- sp->state = IPSEC_SPSTATE_DEAD;
- SPTREE_UNLOCK();
+ key_unlink(sp);
KEY_FREESP(&sp);
{
@@ -2356,8 +2318,9 @@ key_spdacquire(struct secpolicy *sp)
static int
key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
{
+ TAILQ_HEAD(, secpolicy) drainq;
struct sadb_msg *newmsg;
- struct secpolicy *sp;
+ struct secpolicy *sp, *nextsp;
u_int dir;
IPSEC_ASSERT(so != NULL, ("null socket"));
@@ -2368,11 +2331,17 @@ key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg)))
return key_senderror(so, m, EINVAL);
+ TAILQ_INIT(&drainq);
+ SPTREE_WLOCK();
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[dir], chain)
- sp->state = IPSEC_SPSTATE_DEAD;
- SPTREE_UNLOCK();
+ TAILQ_CONCAT(&drainq, &V_sptree[dir], chain);
+ }
+ SPTREE_WUNLOCK();
+ sp = TAILQ_FIRST(&drainq);
+ while (sp != NULL) {
+ nextsp = TAILQ_NEXT(sp, chain);
+ KEY_FREESP(&sp);
+ sp = nextsp;
}
if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) {
@@ -2405,6 +2374,7 @@ key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
static int
key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
{
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
int cnt;
u_int dir;
@@ -2417,20 +2387,20 @@ key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
/* search SPD entry and get buffer size. */
cnt = 0;
- SPTREE_LOCK();
+ SPTREE_RLOCK();
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &V_sptree[dir], chain) {
+ TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
cnt++;
}
}
if (cnt == 0) {
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
return key_senderror(so, m, ENOENT);
}
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
- LIST_FOREACH(sp, &V_sptree[dir], chain) {
+ TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
--cnt;
n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt,
mhp->msg->sadb_msg_pid);
@@ -2440,7 +2410,7 @@ key_spddump(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
}
}
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
m_freem(m);
return 0;
}
@@ -2452,6 +2422,8 @@ key_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq,
struct mbuf *result = NULL, *m;
struct seclifetime lt;
+ SPTREE_RLOCK_ASSERT();
+
m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt);
if (!m)
goto fail;
@@ -4226,47 +4198,29 @@ key_bbcmp(const void *a1, const void *a2, u_int bits)
static void
key_flush_spd(time_t now)
{
- static u_int16_t sptree_scangen = 0;
- u_int16_t gen = sptree_scangen++;
+ SPTREE_RLOCK_TRACKER;
struct secpolicy *sp;
u_int dir;
/* SPD */
for (dir = 0; dir < IPSEC_DIR_MAX; dir++) {
restart:
- SPTREE_LOCK();
- LIST_FOREACH(sp, &V_sptree[dir], chain) {
- if (sp->scangen == gen) /* previously handled */
- continue;
- sp->scangen = gen;
- if (sp->state == IPSEC_SPSTATE_DEAD &&
- sp->refcnt == 1) {
- /*
- * Ensure that we only decrease refcnt once,
- * when we're the last consumer.
- * Directly call SP_DELREF/key_delsp instead
- * of KEY_FREESP to avoid unlocking/relocking
- * SPTREE_LOCK before key_delsp: may refcnt
- * be increased again during that time ?
- * NB: also clean entries created by
- * key_spdflush
- */
- SP_DELREF(sp);
- key_delsp(sp);
- SPTREE_UNLOCK();
- goto restart;
- }
+ SPTREE_RLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[dir], chain) {
if (sp->lifetime == 0 && sp->validtime == 0)
continue;
- if ((sp->lifetime && now - sp->created > sp->lifetime)
- || (sp->validtime && now - sp->lastused > sp->validtime)) {
- sp->state = IPSEC_SPSTATE_DEAD;
- SPTREE_UNLOCK();
+ if ((sp->lifetime &&
+ now - sp->created > sp->lifetime) ||
+ (sp->validtime &&
+ now - sp->lastused > sp->validtime)) {
+ SPTREE_RUNLOCK();
+ key_unlink(sp);
key_spdexpire(sp);
+ KEY_FREESP(&sp);
goto restart;
}
}
- SPTREE_UNLOCK();
+ SPTREE_RUNLOCK();
}
}
@@ -7609,7 +7563,7 @@ key_init(void)
int i;
for (i = 0; i < IPSEC_DIR_MAX; i++)
- LIST_INIT(&V_sptree[i]);
+ TAILQ_INIT(&V_sptree[i]);
LIST_INIT(&V_sahtree);
@@ -7619,10 +7573,6 @@ key_init(void)
LIST_INIT(&V_acqtree);
LIST_INIT(&V_spacqtree);
- /* system default */
- V_ip4_def_policy.policy = IPSEC_POLICY_NONE;
- V_ip4_def_policy.refcnt++; /*never reclaim this*/
-
if (!IS_DEFAULT_VNET(curvnet))
return;
@@ -7647,6 +7597,7 @@ key_init(void)
void
key_destroy(void)
{
+ TAILQ_HEAD(, secpolicy) drainq;
struct secpolicy *sp, *nextsp;
struct secacq *acq, *nextacq;
struct secspacq *spacq, *nextspacq;
@@ -7654,18 +7605,18 @@ key_destroy(void)
struct secreg *reg;
int i;
- SPTREE_LOCK();
+ TAILQ_INIT(&drainq);
+ SPTREE_WLOCK();
for (i = 0; i < IPSEC_DIR_MAX; i++) {
- for (sp = LIST_FIRST(&V_sptree[i]);
- sp != NULL; sp = nextsp) {
- nextsp = LIST_NEXT(sp, chain);
- if (__LIST_CHAINED(sp)) {
- LIST_REMOVE(sp, chain);
- free(sp, M_IPSEC_SP);
- }
- }
+ TAILQ_CONCAT(&drainq, &V_sptree[i], chain);
+ }
+ SPTREE_WUNLOCK();
+ sp = TAILQ_FIRST(&drainq);
+ while (sp != NULL) {
+ nextsp = TAILQ_NEXT(sp, chain);
+ KEY_FREESP(&sp);
+ sp = nextsp;
}
- SPTREE_UNLOCK();
SAHTREE_LOCK();
for (sah = LIST_FIRST(&V_sahtree); sah != NULL; sah = nextsah) {
diff --git a/sys/netipsec/key_debug.c b/sys/netipsec/key_debug.c
index 5cbc1db..97ac061 100644
--- a/sys/netipsec/key_debug.c
+++ b/sys/netipsec/key_debug.c
@@ -463,8 +463,8 @@ kdebug_secpolicy(struct secpolicy *sp)
if (sp == NULL)
panic("%s: NULL pointer was passed.\n", __func__);
- printf("secpolicy{ refcnt=%u state=%u policy=%u\n",
- sp->refcnt, sp->state, sp->policy);
+ printf("secpolicy{ refcnt=%u policy=%u\n",
+ sp->refcnt, sp->policy);
kdebug_secpolicyindex(&sp->spidx);
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index 5e3145e..c5bd4cb 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -1735,9 +1735,6 @@ retry:
goto out;
}
rootdevnames[0] = "nfs:";
-#ifdef NFSCLIENT
- rootdevnames[1] = "oldnfs:";
-#endif
nfs_diskless_valid = 3;
}
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
deleted file mode 100644
index ad9e7a1..0000000
--- a/sys/nfs/nfs_common.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * These functions support the macros and help fiddle mbuf chains for
- * the nfs op functions. They do things like create the rpc header and
- * copy data between mbuf chains and uio lists.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/namei.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/sysent.h>
-#include <sys/syscall.h>
-#include <sys/sysctl.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfs_common.h>
-
-#include <netinet/in.h>
-
-enum vtype nv3tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
-};
-nfstype nfsv3_type[9] = {
- NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON
-};
-
-static void *nfsm_dissect_xx_sub(int s, struct mbuf **md, caddr_t *dpos,
- int how);
-
-SYSCTL_NODE(_vfs, OID_AUTO, nfs_common, CTLFLAG_RD, 0, "NFS common support");
-
-static int nfs_realign_test;
-SYSCTL_INT(_vfs_nfs_common, OID_AUTO, realign_test, CTLFLAG_RD,
- &nfs_realign_test, 0, "Number of realign tests done");
-
-static int nfs_realign_count;
-SYSCTL_INT(_vfs_nfs_common, OID_AUTO, realign_count, CTLFLAG_RD,
- &nfs_realign_count, 0, "Number of mbuf realignments done");
-
-/*
- * copies mbuf chain to the uio scatter/gather list
- */
-int
-nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
-{
- char *mbufcp, *uiocp;
- int xfer, left, len;
- struct mbuf *mp;
- long uiosiz, rem;
- int error = 0;
-
- mp = *mrep;
- mbufcp = *dpos;
- len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
- rem = nfsm_rndup(siz)-siz;
- while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EFBIG);
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- while (len == 0) {
- mp = mp->m_next;
- if (mp == NULL)
- return (EBADRPC);
- mbufcp = mtod(mp, caddr_t);
- len = mp->m_len;
- }
- xfer = (left > len) ? len : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (mbufcp, uiocp, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(mbufcp, uiocp, xfer);
- else
- copyout(mbufcp, uiocp, xfer);
- left -= xfer;
- len -= xfer;
- mbufcp += xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- if (uiop->uio_iov->iov_len <= siz) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- }
- siz -= uiosiz;
- }
- *dpos = mbufcp;
- *mrep = mp;
- if (rem > 0) {
- if (len < rem)
- error = nfs_adv(mrep, dpos, rem, len);
- else
- *dpos += rem;
- }
- return (error);
-}
-
-/*
- * Help break down an mbuf chain by setting the first siz bytes contiguous
- * pointed to by returned val.
- * This is used by the macros nfsm_dissect for tough
- * cases. (The macros use the vars. dpos and dpos2)
- */
-void *
-nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, int how)
-{
- struct mbuf *mp, *mp2;
- int siz2, xfer;
- caddr_t ptr, npos = NULL;
- void *ret;
-
- mp = *mdp;
- while (left == 0) {
- *mdp = mp = mp->m_next;
- if (mp == NULL)
- return (NULL);
- left = mp->m_len;
- *dposp = mtod(mp, caddr_t);
- }
- if (left >= siz) {
- ret = *dposp;
- *dposp += siz;
- } else if (mp->m_next == NULL) {
- return (NULL);
- } else if (siz > MHLEN) {
- panic("nfs S too big");
- } else {
- mp2 = m_get(how, MT_DATA);
- if (mp2 == NULL)
- return (NULL);
- mp2->m_len = siz;
- mp2->m_next = mp->m_next;
- mp->m_next = mp2;
- mp->m_len -= left;
- mp = mp2;
- ptr = mtod(mp, caddr_t);
- ret = ptr;
- bcopy(*dposp, ptr, left); /* Copy what was left */
- siz2 = siz-left;
- ptr += left;
- mp2 = mp->m_next;
- npos = mtod(mp2, caddr_t);
- /* Loop around copying up the siz2 bytes */
- while (siz2 > 0) {
- if (mp2 == NULL)
- return (NULL);
- xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
- if (xfer > 0) {
- bcopy(mtod(mp2, caddr_t), ptr, xfer);
- mp2->m_data += xfer;
- mp2->m_len -= xfer;
- ptr += xfer;
- siz2 -= xfer;
- }
- if (siz2 > 0) {
- mp2 = mp2->m_next;
- if (mp2 != NULL)
- npos = mtod(mp2, caddr_t);
- }
- }
- *mdp = mp2;
- *dposp = mtod(mp2, caddr_t);
- if (!nfsm_aligned(*dposp, u_int32_t)) {
- bcopy(*dposp, npos, mp2->m_len);
- mp2->m_data = npos;
- *dposp = npos;
- }
- }
- return (ret);
-}
-
-/*
- * Advance the position in the mbuf chain.
- */
-int
-nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
-{
- struct mbuf *m;
- int s;
-
- m = *mdp;
- s = left;
- while (s < offs) {
- offs -= s;
- m = m->m_next;
- if (m == NULL)
- return (EBADRPC);
- s = m->m_len;
- }
- *mdp = m;
- *dposp = mtod(m, caddr_t)+offs;
- return (0);
-}
-
-void *
-nfsm_build_xx(int s, struct mbuf **mb, caddr_t *bpos)
-{
- struct mbuf *mb2;
- void *ret;
-
- if (s > M_TRAILINGSPACE(*mb)) {
- mb2 = m_get(M_WAITOK, MT_DATA);
- if (s > MLEN)
- panic("build > MLEN");
- (*mb)->m_next = mb2;
- *mb = mb2;
- (*mb)->m_len = 0;
- *bpos = mtod(*mb, caddr_t);
- }
- ret = *bpos;
- (*mb)->m_len += s;
- *bpos += s;
- return (ret);
-}
-
-void *
-nfsm_dissect_xx(int s, struct mbuf **md, caddr_t *dpos)
-{
-
- return (nfsm_dissect_xx_sub(s, md, dpos, M_WAITOK));
-}
-
-void *
-nfsm_dissect_xx_nonblock(int s, struct mbuf **md, caddr_t *dpos)
-{
-
- return (nfsm_dissect_xx_sub(s, md, dpos, M_NOWAIT));
-}
-
-static void *
-nfsm_dissect_xx_sub(int s, struct mbuf **md, caddr_t *dpos, int how)
-{
- int t1;
- char *cp2;
- void *ret;
-
- t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
- if (t1 >= s) {
- ret = *dpos;
- *dpos += s;
- return (ret);
- }
- cp2 = nfsm_disct(md, dpos, s, t1, how);
- return (cp2);
-}
-
-int
-nfsm_strsiz_xx(int *s, int m, struct mbuf **mb, caddr_t *bpos)
-{
- u_int32_t *tl;
-
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, mb, bpos);
- if (tl == NULL)
- return (EBADRPC);
- *s = fxdr_unsigned(int32_t, *tl);
- if (*s > m)
- return (EBADRPC);
- return (0);
-}
-
-int
-nfsm_adv_xx(int s, struct mbuf **md, caddr_t *dpos)
-{
- int t1;
-
- t1 = mtod(*md, caddr_t) + (*md)->m_len - *dpos;
- if (t1 >= s) {
- *dpos += s;
- return (0);
- }
- t1 = nfs_adv(md, dpos, s, t1);
- if (t1)
- return (t1);
- return (0);
-}
-
-/*
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions of the
- * old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain because
- * the underlying buffers may contain other rpc commands and we cannot afford
- * to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does not
- * occur with NFS/UDP and is supposed to only occassionally occur with TCP.
- * Use vfs.nfs_common.realign_count and realign_test to check this.
- */
-int
-nfs_realign(struct mbuf **pm, int how)
-{
- struct mbuf *m, *n;
- int off;
-
- ++nfs_realign_test;
- while ((m = *pm) != NULL) {
- if (!nfsm_aligned(m->m_len, u_int32_t) ||
- !nfsm_aligned(mtod(m, intptr_t), u_int32_t)) {
- /*
- * NB: we can't depend on m_pkthdr.len to help us
- * decide what to do here. May not be worth doing
- * the m_length calculation as m_copyback will
- * expand the mbuf chain below as needed.
- */
- if (m_length(m, NULL) >= MINCLSIZE) {
- /* NB: m_copyback handles space > MCLBYTES */
- n = m_getcl(how, MT_DATA, 0);
- } else
- n = m_get(how, MT_DATA);
- if (n == NULL)
- return (ENOMEM);
- /*
- * Align the remainder of the mbuf chain.
- */
- n->m_len = 0;
- off = 0;
- while (m != NULL) {
- m_copyback(n, off, m->m_len, mtod(m, caddr_t));
- off += m->m_len;
- m = m->m_next;
- }
- m_freem(*pm);
- *pm = n;
- ++nfs_realign_count;
- break;
- }
- pm = &m->m_next;
- }
- return (0);
-}
-
-static moduledata_t nfs_common_mod = {
- "nfs_common",
- NULL,
- NULL
-};
-
-DECLARE_MODULE(nfs_common, nfs_common_mod, SI_SUB_VFS, SI_ORDER_ANY);
-MODULE_VERSION(nfs_common, 1);
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
deleted file mode 100644
index 1a5b156..0000000
--- a/sys/nfsclient/nfs_bio.c
+++ /dev/null
@@ -1,1794 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <sys/mbuf.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/rwlock.h>
-#include <sys/vmmeter.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-#include <vm/vm_pager.h>
-#include <vm/vnode_pager.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsmount.h>
-#include <nfsclient/nfsnode.h>
-#include <nfs/nfs_kdtrace.h>
-
-static struct buf *nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size,
- struct thread *td);
-static int nfs_directio_write(struct vnode *vp, struct uio *uiop,
- struct ucred *cred, int ioflag);
-
-extern int nfs_directio_enable;
-extern int nfs_directio_allow_mmap;
-
-/*
- * Vnode op for VM getpages.
- */
-int
-nfs_getpages(struct vop_getpages_args *ap)
-{
- int i, error, nextoff, size, toff, count, npages;
- struct uio uio;
- struct iovec iov;
- vm_offset_t kva;
- struct buf *bp;
- struct vnode *vp;
- struct thread *td;
- struct ucred *cred;
- struct nfsmount *nmp;
- vm_object_t object;
- vm_page_t *pages;
- struct nfsnode *np;
-
- vp = ap->a_vp;
- np = VTONFS(vp);
- td = curthread; /* XXX */
- cred = curthread->td_ucred; /* XXX */
- nmp = VFSTONFS(vp->v_mount);
- pages = ap->a_m;
- count = ap->a_count;
-
- if ((object = vp->v_object) == NULL) {
- nfs_printf("nfs_getpages: called with non-merged cache vnode??\n");
- return (VM_PAGER_ERROR);
- }
-
- if (nfs_directio_enable && !nfs_directio_allow_mmap) {
- mtx_lock(&np->n_mtx);
- if ((np->n_flag & NNONCACHE) && (vp->v_type == VREG)) {
- mtx_unlock(&np->n_mtx);
- nfs_printf("nfs_getpages: called on non-cacheable vnode??\n");
- return (VM_PAGER_ERROR);
- } else
- mtx_unlock(&np->n_mtx);
- }
-
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- /* We'll never get here for v4, because we always have fsinfo */
- (void)nfs_fsinfo(nmp, vp, cred, td);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- npages = btoc(count);
-
- /*
- * Since the caller has busied the requested page, that page's valid
- * field will not be changed by other threads.
- */
- vm_page_assert_xbusied(pages[ap->a_reqpage]);
-
- /*
- * If the requested page is partially valid, just return it and
- * allow the pager to zero-out the blanks. Partially valid pages
- * can only occur at the file EOF.
- */
- if (pages[ap->a_reqpage]->valid != 0) {
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages);
- return (VM_PAGER_OK);
- }
-
- /*
- * We use only the kva address for the buffer, but this is extremely
- * convienient and fast.
- */
- bp = getpbuf(&nfs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, pages, npages);
- PCPU_INC(cnt.v_vnodein);
- PCPU_ADD(cnt.v_vnodepgsin, npages);
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = IDX_TO_OFF(pages[0]->pindex);
- uio.uio_resid = count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = td;
-
- error = (nmp->nm_rpcops->nr_readrpc)(vp, &uio, cred);
- pmap_qremove(kva, npages);
-
- relpbuf(bp, &nfs_pbuf_freecnt);
-
- if (error && (uio.uio_resid == count)) {
- nfs_printf("nfs_getpages: error %d\n", error);
- vm_pager_free_nonreq(object, pages, ap->a_reqpage, npages);
- return (VM_PAGER_ERROR);
- }
-
- /*
- * Calculate the number of bytes read and validate only that number
- * of bytes. Note that due to pending writes, size may be 0. This
- * does not mean that the remaining data is invalid!
- */
-
- size = count - uio.uio_resid;
- VM_OBJECT_WLOCK(object);
- for (i = 0, toff = 0; i < npages; i++, toff = nextoff) {
- vm_page_t m;
- nextoff = toff + PAGE_SIZE;
- m = pages[i];
-
- if (nextoff <= size) {
- /*
- * Read operation filled an entire page
- */
- m->valid = VM_PAGE_BITS_ALL;
- KASSERT(m->dirty == 0,
- ("nfs_getpages: page %p is dirty", m));
- } else if (size > toff) {
- /*
- * Read operation filled a partial page.
- */
- m->valid = 0;
- vm_page_set_valid_range(m, 0, size - toff);
- KASSERT(m->dirty == 0,
- ("nfs_getpages: page %p is dirty", m));
- } else {
- /*
- * Read operation was short. If no error
- * occured we may have hit a zero-fill
- * section. We leave valid set to 0, and page
- * is freed by vm_page_readahead_finish() if
- * its index is not equal to requested, or
- * page is zeroed and set valid by
- * vm_pager_get_pages() for requested page.
- */
- ;
- }
- if (i != ap->a_reqpage)
- vm_page_readahead_finish(m);
- }
- VM_OBJECT_WUNLOCK(object);
- return (0);
-}
-
-/*
- * Vnode op for VM putpages.
- */
-int
-nfs_putpages(struct vop_putpages_args *ap)
-{
- struct uio uio;
- struct iovec iov;
- vm_offset_t kva;
- struct buf *bp;
- int iomode, must_commit, i, error, npages, count;
- off_t offset;
- int *rtvals;
- struct vnode *vp;
- struct thread *td;
- struct ucred *cred;
- struct nfsmount *nmp;
- struct nfsnode *np;
- vm_page_t *pages;
-
- vp = ap->a_vp;
- np = VTONFS(vp);
- td = curthread; /* XXX */
- /* Set the cred to n_writecred for the write rpcs. */
- if (np->n_writecred != NULL)
- cred = crhold(np->n_writecred);
- else
- cred = crhold(curthread->td_ucred); /* XXX */
- nmp = VFSTONFS(vp->v_mount);
- pages = ap->a_m;
- count = ap->a_count;
- rtvals = ap->a_rtvals;
- npages = btoc(count);
- offset = IDX_TO_OFF(pages[0]->pindex);
-
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- (void)nfs_fsinfo(nmp, vp, cred, td);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- mtx_lock(&np->n_mtx);
- if (nfs_directio_enable && !nfs_directio_allow_mmap &&
- (np->n_flag & NNONCACHE) && (vp->v_type == VREG)) {
- mtx_unlock(&np->n_mtx);
- nfs_printf("nfs_putpages: called on noncache-able vnode??\n");
- mtx_lock(&np->n_mtx);
- }
-
- for (i = 0; i < npages; i++)
- rtvals[i] = VM_PAGER_ERROR;
-
- /*
- * When putting pages, do not extend file past EOF.
- */
- if (offset + count > np->n_size) {
- count = np->n_size - offset;
- if (count < 0)
- count = 0;
- }
- mtx_unlock(&np->n_mtx);
-
- /*
- * We use only the kva address for the buffer, but this is extremely
- * convienient and fast.
- */
- bp = getpbuf(&nfs_pbuf_freecnt);
-
- kva = (vm_offset_t) bp->b_data;
- pmap_qenter(kva, pages, npages);
- PCPU_INC(cnt.v_vnodeout);
- PCPU_ADD(cnt.v_vnodepgsout, count);
-
- iov.iov_base = (caddr_t) kva;
- iov.iov_len = count;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = offset;
- uio.uio_resid = count;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_WRITE;
- uio.uio_td = td;
-
- if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0)
- iomode = NFSV3WRITE_UNSTABLE;
- else
- iomode = NFSV3WRITE_FILESYNC;
-
- error = (nmp->nm_rpcops->nr_writerpc)(vp, &uio, cred, &iomode, &must_commit);
- crfree(cred);
-
- pmap_qremove(kva, npages);
- relpbuf(bp, &nfs_pbuf_freecnt);
-
- if (!error) {
- vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
- if (must_commit) {
- nfs_clearcommit(vp->v_mount);
- }
- }
- return rtvals[0];
-}
-
-/*
- * For nfs, cache consistency can only be maintained approximately.
- * Although RFC1094 does not specify the criteria, the following is
- * believed to be compatible with the reference port.
- * For nfs:
- * If the file's modify time on the server has changed since the
- * last read rpc or you have written to the file,
- * you may have lost data cache consistency with the
- * server, so flush all of the file's data out of the cache.
- * Then force a getattr rpc to ensure that you have up to date
- * attributes.
- * NB: This implies that cache data can be read when up to
- * NFS_ATTRTIMEO seconds out of date. If you find that you need current
- * attributes this could be forced by setting n_attrstamp to 0 before
- * the VOP_GETATTR() call.
- */
-static inline int
-nfs_bioread_check_cons(struct vnode *vp, struct thread *td, struct ucred *cred)
-{
- int error = 0;
- struct vattr vattr;
- struct nfsnode *np = VTONFS(vp);
- int old_lock;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
-
- /*
- * Grab the exclusive lock before checking whether the cache is
- * consistent.
- * XXX - We can make this cheaper later (by acquiring cheaper locks).
- * But for now, this suffices.
- */
- old_lock = nfs_upgrade_vnlock(vp);
- if (vp->v_iflag & VI_DOOMED) {
- nfs_downgrade_vnlock(vp, old_lock);
- return (EBADF);
- }
-
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NMODIFIED) {
- mtx_unlock(&np->n_mtx);
- if (vp->v_type != VREG) {
- if (vp->v_type != VDIR)
- panic("nfs: bioread, not dir");
- (nmp->nm_rpcops->nr_invaldir)(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
- goto out;
- }
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- error = VOP_GETATTR(vp, &vattr, cred);
- if (error)
- goto out;
- mtx_lock(&np->n_mtx);
- np->n_mtime = vattr.va_mtime;
- mtx_unlock(&np->n_mtx);
- } else {
- mtx_unlock(&np->n_mtx);
- error = VOP_GETATTR(vp, &vattr, cred);
- if (error)
- return (error);
- mtx_lock(&np->n_mtx);
- if ((np->n_flag & NSIZECHANGED)
- || (NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime))) {
- mtx_unlock(&np->n_mtx);
- if (vp->v_type == VDIR)
- (nmp->nm_rpcops->nr_invaldir)(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
- goto out;
- mtx_lock(&np->n_mtx);
- np->n_mtime = vattr.va_mtime;
- np->n_flag &= ~NSIZECHANGED;
- }
- mtx_unlock(&np->n_mtx);
- }
-out:
- nfs_downgrade_vnlock(vp, old_lock);
- return error;
-}
-
-/*
- * Vnode op for read using bio
- */
-int
-nfs_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
-{
- struct nfsnode *np = VTONFS(vp);
- int biosize, i;
- struct buf *bp, *rabp;
- struct thread *td;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- daddr_t lbn, rabn;
- off_t end;
- int bcount;
- int seqcount;
- int nra, error = 0, n = 0, on = 0;
-
- KASSERT(uio->uio_rw == UIO_READ, ("nfs_read mode"));
- if (uio->uio_resid == 0)
- return (0);
- if (uio->uio_offset < 0) /* XXX VDIR cookies can be negative */
- return (EINVAL);
- td = uio->uio_td;
-
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- (void)nfs_fsinfo(nmp, vp, cred, td);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- end = uio->uio_offset + uio->uio_resid;
- if (vp->v_type != VDIR &&
- (end > nmp->nm_maxfilesize || end < uio->uio_offset))
- return (EFBIG);
-
- if (nfs_directio_enable && (ioflag & IO_DIRECT) && (vp->v_type == VREG))
- /* No caching/ no readaheads. Just read data into the user buffer */
- return nfs_readrpc(vp, uio, cred);
-
- biosize = vp->v_bufobj.bo_bsize;
- seqcount = (int)((off_t)(ioflag >> IO_SEQSHIFT) * biosize / BKVASIZE);
-
- error = nfs_bioread_check_cons(vp, td, cred);
- if (error)
- return error;
-
- do {
- u_quad_t nsize;
-
- mtx_lock(&np->n_mtx);
- nsize = np->n_size;
- mtx_unlock(&np->n_mtx);
-
- switch (vp->v_type) {
- case VREG:
- nfsstats.biocache_reads++;
- lbn = uio->uio_offset / biosize;
- on = uio->uio_offset - (lbn * biosize);
-
- /*
- * Start the read ahead(s), as required.
- */
- if (nmp->nm_readahead > 0) {
- for (nra = 0; nra < nmp->nm_readahead && nra < seqcount &&
- (off_t)(lbn + 1 + nra) * biosize < nsize; nra++) {
- rabn = lbn + 1 + nra;
- if (incore(&vp->v_bufobj, rabn) == NULL) {
- rabp = nfs_getcacheblk(vp, rabn, biosize, td);
- if (!rabp) {
- error = nfs_sigintr(nmp, td);
- return (error ? error : EINTR);
- }
- if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
- rabp->b_flags |= B_ASYNC;
- rabp->b_iocmd = BIO_READ;
- vfs_busy_pages(rabp, 0);
- if (nfs_asyncio(nmp, rabp, cred, td)) {
- rabp->b_flags |= B_INVAL;
- rabp->b_ioflags |= BIO_ERROR;
- vfs_unbusy_pages(rabp);
- brelse(rabp);
- break;
- }
- } else {
- brelse(rabp);
- }
- }
- }
- }
-
- /* Note that bcount is *not* DEV_BSIZE aligned. */
- bcount = biosize;
- if ((off_t)lbn * biosize >= nsize) {
- bcount = 0;
- } else if ((off_t)(lbn + 1) * biosize > nsize) {
- bcount = nsize - (off_t)lbn * biosize;
- }
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
-
- if (!bp) {
- error = nfs_sigintr(nmp, td);
- return (error ? error : EINTR);
- }
-
- /*
- * If B_CACHE is not set, we must issue the read. If this
- * fails, we return an error.
- */
-
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(vp, bp, cred, td);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
-
- /*
- * on is the offset into the current bp. Figure out how many
- * bytes we can copy out of the bp. Note that bcount is
- * NOT DEV_BSIZE aligned.
- *
- * Then figure out how many bytes we can copy into the uio.
- */
-
- n = 0;
- if (on < bcount)
- n = MIN((unsigned)(bcount - on), uio->uio_resid);
- break;
- case VLNK:
- nfsstats.biocache_readlinks++;
- bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td);
- if (!bp) {
- error = nfs_sigintr(nmp, td);
- return (error ? error : EINTR);
- }
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(vp, bp, cred, td);
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- brelse(bp);
- return (error);
- }
- }
- n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
- on = 0;
- break;
- case VDIR:
- nfsstats.biocache_readdirs++;
- if (np->n_direofoffset
- && uio->uio_offset >= np->n_direofoffset) {
- return (0);
- }
- lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ;
- on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
- bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td);
- if (!bp) {
- error = nfs_sigintr(nmp, td);
- return (error ? error : EINTR);
- }
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(vp, bp, cred, td);
- if (error) {
- brelse(bp);
- }
- while (error == NFSERR_BAD_COOKIE) {
- (nmp->nm_rpcops->nr_invaldir)(vp);
- error = nfs_vinvalbuf(vp, 0, td, 1);
- /*
- * Yuck! The directory has been modified on the
- * server. The only way to get the block is by
- * reading from the beginning to get all the
- * offset cookies.
- *
- * Leave the last bp intact unless there is an error.
- * Loop back up to the while if the error is another
- * NFSERR_BAD_COOKIE (double yuch!).
- */
- for (i = 0; i <= lbn && !error; i++) {
- if (np->n_direofoffset
- && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset)
- return (0);
- bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, td);
- if (!bp) {
- error = nfs_sigintr(nmp, td);
- return (error ? error : EINTR);
- }
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(vp, bp, cred, td);
- /*
- * no error + B_INVAL == directory EOF,
- * use the block.
- */
- if (error == 0 && (bp->b_flags & B_INVAL))
- break;
- }
- /*
- * An error will throw away the block and the
- * for loop will break out. If no error and this
- * is not the block we want, we throw away the
- * block and go for the next one via the for loop.
- */
- if (error || i < lbn)
- brelse(bp);
- }
- }
- /*
- * The above while is repeated if we hit another cookie
- * error. If we hit an error and it wasn't a cookie error,
- * we give up.
- */
- if (error)
- return (error);
- }
-
- /*
- * If not eof and read aheads are enabled, start one.
- * (You need the current block first, so that you have the
- * directory offset cookie of the next block.)
- */
- if (nmp->nm_readahead > 0 &&
- (bp->b_flags & B_INVAL) == 0 &&
- (np->n_direofoffset == 0 ||
- (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
- incore(&vp->v_bufobj, lbn + 1) == NULL) {
- rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, td);
- if (rabp) {
- if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
- rabp->b_flags |= B_ASYNC;
- rabp->b_iocmd = BIO_READ;
- vfs_busy_pages(rabp, 0);
- if (nfs_asyncio(nmp, rabp, cred, td)) {
- rabp->b_flags |= B_INVAL;
- rabp->b_ioflags |= BIO_ERROR;
- vfs_unbusy_pages(rabp);
- brelse(rabp);
- }
- } else {
- brelse(rabp);
- }
- }
- }
- /*
- * Unlike VREG files, whos buffer size ( bp->b_bcount ) is
- * chopped for the EOF condition, we cannot tell how large
- * NFS directories are going to be until we hit EOF. So
- * an NFS directory buffer is *not* chopped to its EOF. Now,
- * it just so happens that b_resid will effectively chop it
- * to EOF. *BUT* this information is lost if the buffer goes
- * away and is reconstituted into a B_CACHE state ( due to
- * being VMIO ) later. So we keep track of the directory eof
- * in np->n_direofoffset and chop it off as an extra step
- * right here.
- */
- n = lmin(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
- if (np->n_direofoffset && n > np->n_direofoffset - uio->uio_offset)
- n = np->n_direofoffset - uio->uio_offset;
- break;
- default:
- nfs_printf(" nfs_bioread: type %x unexpected\n", vp->v_type);
- bp = NULL;
- break;
- };
-
- if (n > 0) {
- error = uiomove(bp->b_data + on, (int)n, uio);
- }
- if (vp->v_type == VLNK)
- n = 0;
- if (bp != NULL)
- brelse(bp);
- } while (error == 0 && uio->uio_resid > 0 && n > 0);
- return (error);
-}
-
-/*
- * The NFS write path cannot handle iovecs with len > 1. So we need to
- * break up iovecs accordingly (restricting them to wsize).
- * For the SYNC case, we can do this with 1 copy (user buffer -> mbuf).
- * For the ASYNC case, 2 copies are needed. The first a copy from the
- * user buffer to a staging buffer and then a second copy from the staging
- * buffer to mbufs. This can be optimized by copying from the user buffer
- * directly into mbufs and passing the chain down, but that requires a
- * fair amount of re-working of the relevant codepaths (and can be done
- * later).
- */
-static int
-nfs_directio_write(vp, uiop, cred, ioflag)
- struct vnode *vp;
- struct uio *uiop;
- struct ucred *cred;
- int ioflag;
-{
- int error;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct thread *td = uiop->uio_td;
- int size;
- int wsize;
-
- mtx_lock(&nmp->nm_mtx);
- wsize = nmp->nm_wsize;
- mtx_unlock(&nmp->nm_mtx);
- if (ioflag & IO_SYNC) {
- int iomode, must_commit;
- struct uio uio;
- struct iovec iov;
-do_sync:
- while (uiop->uio_resid > 0) {
- size = MIN(uiop->uio_resid, wsize);
- size = MIN(uiop->uio_iov->iov_len, size);
- iov.iov_base = uiop->uio_iov->iov_base;
- iov.iov_len = size;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = uiop->uio_offset;
- uio.uio_resid = size;
- uio.uio_segflg = UIO_USERSPACE;
- uio.uio_rw = UIO_WRITE;
- uio.uio_td = td;
- iomode = NFSV3WRITE_FILESYNC;
- error = (nmp->nm_rpcops->nr_writerpc)(vp, &uio, cred,
- &iomode, &must_commit);
- KASSERT((must_commit == 0),
- ("nfs_directio_write: Did not commit write"));
- if (error)
- return (error);
- uiop->uio_offset += size;
- uiop->uio_resid -= size;
- if (uiop->uio_iov->iov_len <= size) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + size;
- uiop->uio_iov->iov_len -= size;
- }
- }
- } else {
- struct uio *t_uio;
- struct iovec *t_iov;
- struct buf *bp;
-
- /*
- * Break up the write into blocksize chunks and hand these
- * over to nfsiod's for write back.
- * Unfortunately, this incurs a copy of the data. Since
- * the user could modify the buffer before the write is
- * initiated.
- *
- * The obvious optimization here is that one of the 2 copies
- * in the async write path can be eliminated by copying the
- * data here directly into mbufs and passing the mbuf chain
- * down. But that will require a fair amount of re-working
- * of the code and can be done if there's enough interest
- * in NFS directio access.
- */
- while (uiop->uio_resid > 0) {
- size = MIN(uiop->uio_resid, wsize);
- size = MIN(uiop->uio_iov->iov_len, size);
- bp = getpbuf(&nfs_pbuf_freecnt);
- t_uio = malloc(sizeof(struct uio), M_NFSDIRECTIO, M_WAITOK);
- t_iov = malloc(sizeof(struct iovec), M_NFSDIRECTIO, M_WAITOK);
- t_iov->iov_base = malloc(size, M_NFSDIRECTIO, M_WAITOK);
- t_iov->iov_len = size;
- t_uio->uio_iov = t_iov;
- t_uio->uio_iovcnt = 1;
- t_uio->uio_offset = uiop->uio_offset;
- t_uio->uio_resid = size;
- t_uio->uio_segflg = UIO_SYSSPACE;
- t_uio->uio_rw = UIO_WRITE;
- t_uio->uio_td = td;
- KASSERT(uiop->uio_segflg == UIO_USERSPACE ||
- uiop->uio_segflg == UIO_SYSSPACE,
- ("nfs_directio_write: Bad uio_segflg"));
- if (uiop->uio_segflg == UIO_USERSPACE) {
- error = copyin(uiop->uio_iov->iov_base,
- t_iov->iov_base, size);
- if (error != 0)
- goto err_free;
- } else
- /*
- * UIO_SYSSPACE may never happen, but handle
- * it just in case it does.
- */
- bcopy(uiop->uio_iov->iov_base, t_iov->iov_base,
- size);
- bp->b_flags |= B_DIRECT;
- bp->b_iocmd = BIO_WRITE;
- if (cred != NOCRED) {
- crhold(cred);
- bp->b_wcred = cred;
- } else
- bp->b_wcred = NOCRED;
- bp->b_caller1 = (void *)t_uio;
- bp->b_vp = vp;
- error = nfs_asyncio(nmp, bp, NOCRED, td);
-err_free:
- if (error) {
- free(t_iov->iov_base, M_NFSDIRECTIO);
- free(t_iov, M_NFSDIRECTIO);
- free(t_uio, M_NFSDIRECTIO);
- bp->b_vp = NULL;
- relpbuf(bp, &nfs_pbuf_freecnt);
- if (error == EINTR)
- return (error);
- goto do_sync;
- }
- uiop->uio_offset += size;
- uiop->uio_resid -= size;
- if (uiop->uio_iov->iov_len <= size) {
- uiop->uio_iovcnt--;
- uiop->uio_iov++;
- } else {
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + size;
- uiop->uio_iov->iov_len -= size;
- }
- }
- }
- return (0);
-}
-
-/*
- * Vnode op for write using bio
- */
-int
-nfs_write(struct vop_write_args *ap)
-{
- int biosize;
- struct uio *uio = ap->a_uio;
- struct thread *td = uio->uio_td;
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct ucred *cred = ap->a_cred;
- int ioflag = ap->a_ioflag;
- struct buf *bp;
- struct vattr vattr;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- daddr_t lbn;
- off_t end;
- int bcount;
- int n, on, error = 0;
-
- KASSERT(uio->uio_rw == UIO_WRITE, ("nfs_write mode"));
- KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
- ("nfs_write proc"));
- if (vp->v_type != VREG)
- return (EIO);
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NWRITEERR) {
- np->n_flag &= ~NWRITEERR;
- mtx_unlock(&np->n_mtx);
- return (np->n_error);
- } else
- mtx_unlock(&np->n_mtx);
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
- (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- (void)nfs_fsinfo(nmp, vp, cred, td);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- /*
- * Synchronously flush pending buffers if we are in synchronous
- * mode or if we are appending.
- */
- if (ioflag & (IO_APPEND | IO_SYNC)) {
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NMODIFIED) {
- mtx_unlock(&np->n_mtx);
-#ifdef notyet /* Needs matching nonblock semantics elsewhere, too. */
- /*
- * Require non-blocking, synchronous writes to
- * dirty files to inform the program it needs
- * to fsync(2) explicitly.
- */
- if (ioflag & IO_NDELAY)
- return (EAGAIN);
-#endif
-flush_and_restart:
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- error = nfs_vinvalbuf(vp, V_SAVE, td, 1);
- if (error)
- return (error);
- } else
- mtx_unlock(&np->n_mtx);
- }
-
- /*
- * If IO_APPEND then load uio_offset. We restart here if we cannot
- * get the append lock.
- */
- if (ioflag & IO_APPEND) {
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- error = VOP_GETATTR(vp, &vattr, cred);
- if (error)
- return (error);
- mtx_lock(&np->n_mtx);
- uio->uio_offset = np->n_size;
- mtx_unlock(&np->n_mtx);
- }
-
- if (uio->uio_offset < 0)
- return (EINVAL);
- end = uio->uio_offset + uio->uio_resid;
- if (end > nmp->nm_maxfilesize || end < uio->uio_offset)
- return (EFBIG);
- if (uio->uio_resid == 0)
- return (0);
-
- if (nfs_directio_enable && (ioflag & IO_DIRECT) && vp->v_type == VREG)
- return nfs_directio_write(vp, uio, cred, ioflag);
-
- /*
- * Maybe this should be above the vnode op call, but so long as
- * file servers have no limits, i don't think it matters
- */
- if (vn_rlimit_fsize(vp, uio, td))
- return (EFBIG);
-
- biosize = vp->v_bufobj.bo_bsize;
- /*
- * Find all of this file's B_NEEDCOMMIT buffers. If our writes
- * would exceed the local maximum per-file write commit size when
- * combined with those, we must decide whether to flush,
- * go synchronous, or return error. We don't bother checking
- * IO_UNIT -- we just make all writes atomic anyway, as there's
- * no point optimizing for something that really won't ever happen.
- */
- if (!(ioflag & IO_SYNC)) {
- int nflag;
-
- mtx_lock(&np->n_mtx);
- nflag = np->n_flag;
- mtx_unlock(&np->n_mtx);
- int needrestart = 0;
- if (nmp->nm_wcommitsize < uio->uio_resid) {
- /*
- * If this request could not possibly be completed
- * without exceeding the maximum outstanding write
- * commit size, see if we can convert it into a
- * synchronous write operation.
- */
- if (ioflag & IO_NDELAY)
- return (EAGAIN);
- ioflag |= IO_SYNC;
- if (nflag & NMODIFIED)
- needrestart = 1;
- } else if (nflag & NMODIFIED) {
- int wouldcommit = 0;
- BO_LOCK(&vp->v_bufobj);
- if (vp->v_bufobj.bo_dirty.bv_cnt != 0) {
- TAILQ_FOREACH(bp, &vp->v_bufobj.bo_dirty.bv_hd,
- b_bobufs) {
- if (bp->b_flags & B_NEEDCOMMIT)
- wouldcommit += bp->b_bcount;
- }
- }
- BO_UNLOCK(&vp->v_bufobj);
- /*
- * Since we're not operating synchronously and
- * bypassing the buffer cache, we are in a commit
- * and holding all of these buffers whether
- * transmitted or not. If not limited, this
- * will lead to the buffer cache deadlocking,
- * as no one else can flush our uncommitted buffers.
- */
- wouldcommit += uio->uio_resid;
- /*
- * If we would initially exceed the maximum
- * outstanding write commit size, flush and restart.
- */
- if (wouldcommit > nmp->nm_wcommitsize)
- needrestart = 1;
- }
- if (needrestart)
- goto flush_and_restart;
- }
-
- do {
- nfsstats.biocache_writes++;
- lbn = uio->uio_offset / biosize;
- on = uio->uio_offset - (lbn * biosize);
- n = MIN((unsigned)(biosize - on), uio->uio_resid);
-again:
- /*
- * Handle direct append and file extension cases, calculate
- * unaligned buffer size.
- */
- mtx_lock(&np->n_mtx);
- if (uio->uio_offset == np->n_size && n) {
- mtx_unlock(&np->n_mtx);
- /*
- * Get the buffer (in its pre-append state to maintain
- * B_CACHE if it was previously set). Resize the
- * nfsnode after we have locked the buffer to prevent
- * readers from reading garbage.
- */
- bcount = on;
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
-
- if (bp != NULL) {
- long save;
-
- mtx_lock(&np->n_mtx);
- np->n_size = uio->uio_offset + n;
- np->n_flag |= NMODIFIED;
- vnode_pager_setsize(vp, np->n_size);
- mtx_unlock(&np->n_mtx);
-
- save = bp->b_flags & B_CACHE;
- bcount += n;
- allocbuf(bp, bcount);
- bp->b_flags |= save;
- }
- } else {
- /*
- * Obtain the locked cache block first, and then
- * adjust the file's size as appropriate.
- */
- bcount = on + n;
- if ((off_t)lbn * biosize + bcount < np->n_size) {
- if ((off_t)(lbn + 1) * biosize < np->n_size)
- bcount = biosize;
- else
- bcount = np->n_size - (off_t)lbn * biosize;
- }
- mtx_unlock(&np->n_mtx);
- bp = nfs_getcacheblk(vp, lbn, bcount, td);
- mtx_lock(&np->n_mtx);
- if (uio->uio_offset + n > np->n_size) {
- np->n_size = uio->uio_offset + n;
- np->n_flag |= NMODIFIED;
- vnode_pager_setsize(vp, np->n_size);
- }
- mtx_unlock(&np->n_mtx);
- }
-
- if (!bp) {
- error = nfs_sigintr(nmp, td);
- if (!error)
- error = EINTR;
- break;
- }
-
- /*
- * Issue a READ if B_CACHE is not set. In special-append
- * mode, B_CACHE is based on the buffer prior to the write
- * op and is typically set, avoiding the read. If a read
- * is required in special append mode, the server will
- * probably send us a short-read since we extended the file
- * on our end, resulting in b_resid == 0 and, thusly,
- * B_CACHE getting set.
- *
- * We can also avoid issuing the read if the write covers
- * the entire buffer. We have to make sure the buffer state
- * is reasonable in this case since we will not be initiating
- * I/O. See the comments in kern/vfs_bio.c's getblk() for
- * more information.
- *
- * B_CACHE may also be set due to the buffer being cached
- * normally.
- */
-
- if (on == 0 && n == bcount) {
- bp->b_flags |= B_CACHE;
- bp->b_flags &= ~B_INVAL;
- bp->b_ioflags &= ~BIO_ERROR;
- }
-
- if ((bp->b_flags & B_CACHE) == 0) {
- bp->b_iocmd = BIO_READ;
- vfs_busy_pages(bp, 0);
- error = nfs_doio(vp, bp, cred, td);
- if (error) {
- brelse(bp);
- break;
- }
- }
- if (bp->b_wcred == NOCRED)
- bp->b_wcred = crhold(cred);
- mtx_lock(&np->n_mtx);
- np->n_flag |= NMODIFIED;
- mtx_unlock(&np->n_mtx);
-
- /*
- * If dirtyend exceeds file size, chop it down. This should
- * not normally occur but there is an append race where it
- * might occur XXX, so we log it.
- *
- * If the chopping creates a reverse-indexed or degenerate
- * situation with dirtyoff/end, we 0 both of them.
- */
-
- if (bp->b_dirtyend > bcount) {
- nfs_printf("NFS append race @%lx:%d\n",
- (long)bp->b_blkno * DEV_BSIZE,
- bp->b_dirtyend - bcount);
- bp->b_dirtyend = bcount;
- }
-
- if (bp->b_dirtyoff >= bp->b_dirtyend)
- bp->b_dirtyoff = bp->b_dirtyend = 0;
-
- /*
- * If the new write will leave a contiguous dirty
- * area, just update the b_dirtyoff and b_dirtyend,
- * otherwise force a write rpc of the old dirty area.
- *
- * While it is possible to merge discontiguous writes due to
- * our having a B_CACHE buffer ( and thus valid read data
- * for the hole), we don't because it could lead to
- * significant cache coherency problems with multiple clients,
- * especially if locking is implemented later on.
- *
- * as an optimization we could theoretically maintain
- * a linked list of discontinuous areas, but we would still
- * have to commit them separately so there isn't much
- * advantage to it except perhaps a bit of asynchronization.
- */
-
- if (bp->b_dirtyend > 0 &&
- (on > bp->b_dirtyend || (on + n) < bp->b_dirtyoff)) {
- if (bwrite(bp) == EINTR) {
- error = EINTR;
- break;
- }
- goto again;
- }
-
- error = uiomove((char *)bp->b_data + on, n, uio);
-
- /*
- * Since this block is being modified, it must be written
- * again and not just committed. Since write clustering does
- * not work for the stage 1 data write, only the stage 2
- * commit rpc, we have to clear B_CLUSTEROK as well.
- */
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
-
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- brelse(bp);
- break;
- }
-
- /*
- * Only update dirtyoff/dirtyend if not a degenerate
- * condition.
- */
- if (n) {
- if (bp->b_dirtyend > 0) {
- bp->b_dirtyoff = min(on, bp->b_dirtyoff);
- bp->b_dirtyend = max((on + n), bp->b_dirtyend);
- } else {
- bp->b_dirtyoff = on;
- bp->b_dirtyend = on + n;
- }
- vfs_bio_set_valid(bp, on, n);
- }
-
- /*
- * If IO_SYNC do bwrite().
- *
- * IO_INVAL appears to be unused. The idea appears to be
- * to turn off caching in this case. Very odd. XXX
- */
- if ((ioflag & IO_SYNC)) {
- if (ioflag & IO_INVAL)
- bp->b_flags |= B_NOCACHE;
- error = bwrite(bp);
- if (error)
- break;
- } else if ((n + on) == biosize) {
- bp->b_flags |= B_ASYNC;
- (void) (nmp->nm_rpcops->nr_writebp)(bp, 0, NULL);
- } else {
- bdwrite(bp);
- }
- } while (uio->uio_resid > 0 && n > 0);
-
- return (error);
-}
-
-/*
- * Get an nfs cache block.
- *
- * Allocate a new one if the block isn't currently in the cache
- * and return the block marked busy. If the calling process is
- * interrupted by a signal for an interruptible mount point, return
- * NULL.
- *
- * The caller must carefully deal with the possible B_INVAL state of
- * the buffer. nfs_doio() clears B_INVAL (and nfs_asyncio() clears it
- * indirectly), so synchronous reads can be issued without worrying about
- * the B_INVAL state. We have to be a little more careful when dealing
- * with writes (see comments in nfs_write()) when extending a file past
- * its EOF.
- */
-static struct buf *
-nfs_getcacheblk(struct vnode *vp, daddr_t bn, int size, struct thread *td)
-{
- struct buf *bp;
- struct mount *mp;
- struct nfsmount *nmp;
-
- mp = vp->v_mount;
- nmp = VFSTONFS(mp);
-
- if (nmp->nm_flag & NFSMNT_INT) {
- sigset_t oldset;
-
- nfs_set_sigmask(td, &oldset);
- bp = getblk(vp, bn, size, PCATCH, 0, 0);
- nfs_restore_sigmask(td, &oldset);
- while (bp == NULL) {
- if (nfs_sigintr(nmp, td))
- return (NULL);
- bp = getblk(vp, bn, size, 0, 2 * hz, 0);
- }
- } else {
- bp = getblk(vp, bn, size, 0, 0, 0);
- }
-
- if (vp->v_type == VREG)
- bp->b_blkno = bn * (vp->v_bufobj.bo_bsize / DEV_BSIZE);
- return (bp);
-}
-
-/*
- * Flush and invalidate all dirty buffers. If another process is already
- * doing the flush, just wait for completion.
- */
-int
-nfs_vinvalbuf(struct vnode *vp, int flags, struct thread *td, int intrflg)
-{
- struct nfsnode *np = VTONFS(vp);
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int error = 0, slpflag, slptimeo;
- int old_lock = 0;
-
- ASSERT_VOP_LOCKED(vp, "nfs_vinvalbuf");
-
- if ((nmp->nm_flag & NFSMNT_INT) == 0)
- intrflg = 0;
- if (intrflg) {
- slpflag = PCATCH;
- slptimeo = 2 * hz;
- } else {
- slpflag = 0;
- slptimeo = 0;
- }
-
- old_lock = nfs_upgrade_vnlock(vp);
- if (vp->v_iflag & VI_DOOMED) {
- /*
- * Since vgonel() uses the generic vinvalbuf() to flush
- * dirty buffers and it does not call this function, it
- * is safe to just return OK when VI_DOOMED is set.
- */
- nfs_downgrade_vnlock(vp, old_lock);
- return (0);
- }
-
- /*
- * Now, flush as required.
- */
- if ((flags & V_SAVE) && (vp->v_bufobj.bo_object != NULL)) {
- VM_OBJECT_WLOCK(vp->v_bufobj.bo_object);
- vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
- VM_OBJECT_WUNLOCK(vp->v_bufobj.bo_object);
- /*
- * If the page clean was interrupted, fail the invalidation.
- * Not doing so, we run the risk of losing dirty pages in the
- * vinvalbuf() call below.
- */
- if (intrflg && (error = nfs_sigintr(nmp, td)))
- goto out;
- }
-
- error = vinvalbuf(vp, flags, slpflag, 0);
- while (error) {
- if (intrflg && (error = nfs_sigintr(nmp, td)))
- goto out;
- error = vinvalbuf(vp, flags, 0, slptimeo);
- }
- mtx_lock(&np->n_mtx);
- if (np->n_directio_asyncwr == 0)
- np->n_flag &= ~NMODIFIED;
- mtx_unlock(&np->n_mtx);
-out:
- nfs_downgrade_vnlock(vp, old_lock);
- return error;
-}
-
-/*
- * Initiate asynchronous I/O. Return an error if no nfsiods are available.
- * This is mainly to avoid queueing async I/O requests when the nfsiods
- * are all hung on a dead server.
- *
- * Note: nfs_asyncio() does not clear (BIO_ERROR|B_INVAL) but when the bp
- * is eventually dequeued by the async daemon, nfs_doio() *will*.
- */
-int
-nfs_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thread *td)
-{
- int iod;
- int gotiod;
- int slpflag = 0;
- int slptimeo = 0;
- int error, error2;
-
- /*
- * Commits are usually short and sweet so lets save some cpu and
- * leave the async daemons for more important rpc's (such as reads
- * and writes).
- *
- * Readdirplus RPCs do vget()s to acquire the vnodes for entries
- * in the directory in order to update attributes. This can deadlock
- * with another thread that is waiting for async I/O to be done by
- * an nfsiod thread while holding a lock on one of these vnodes.
- * To avoid this deadlock, don't allow the async nfsiod threads to
- * perform Readdirplus RPCs.
- */
- mtx_lock(&nfs_iod_mtx);
- if ((bp->b_iocmd == BIO_WRITE && (bp->b_flags & B_NEEDCOMMIT) &&
- (nmp->nm_bufqiods > nfs_numasync / 2)) ||
- (bp->b_vp->v_type == VDIR && (nmp->nm_flag & NFSMNT_RDIRPLUS))) {
- mtx_unlock(&nfs_iod_mtx);
- return(EIO);
- }
-again:
- if (nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- gotiod = FALSE;
-
- /*
- * Find a free iod to process this request.
- */
- for (iod = 0; iod < nfs_numasync; iod++)
- if (nfs_iodwant[iod] == NFSIOD_AVAILABLE) {
- gotiod = TRUE;
- break;
- }
-
- /*
- * Try to create one if none are free.
- */
- if (!gotiod)
- nfs_nfsiodnew();
- else {
- /*
- * Found one, so wake it up and tell it which
- * mount to process.
- */
- NFS_DPF(ASYNCIO, ("nfs_asyncio: waking iod %d for mount %p\n",
- iod, nmp));
- nfs_iodwant[iod] = NFSIOD_NOT_AVAILABLE;
- nfs_iodmount[iod] = nmp;
- nmp->nm_bufqiods++;
- wakeup(&nfs_iodwant[iod]);
- }
-
- /*
- * If none are free, we may already have an iod working on this mount
- * point. If so, it will process our request.
- */
- if (!gotiod) {
- if (nmp->nm_bufqiods > 0) {
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: %d iods are already processing mount %p\n",
- nmp->nm_bufqiods, nmp));
- gotiod = TRUE;
- }
- }
-
- /*
- * If we have an iod which can process the request, then queue
- * the buffer.
- */
- if (gotiod) {
- /*
- * Ensure that the queue never grows too large. We still want
- * to asynchronize so we block rather then return EIO.
- */
- while (nmp->nm_bufqlen >= 2 * nfs_numasync) {
- NFS_DPF(ASYNCIO,
- ("nfs_asyncio: waiting for mount %p queue to drain\n", nmp));
- nmp->nm_bufqwant = TRUE;
- error = nfs_msleep(td, &nmp->nm_bufq, &nfs_iod_mtx,
- slpflag | PRIBIO,
- "nfsaio", slptimeo);
- if (error) {
- error2 = nfs_sigintr(nmp, td);
- if (error2) {
- mtx_unlock(&nfs_iod_mtx);
- return (error2);
- }
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- /*
- * We might have lost our iod while sleeping,
- * so check and loop if nescessary.
- */
- goto again;
- }
-
- /* We might have lost our nfsiod */
- if (nmp->nm_bufqiods == 0) {
- NFS_DPF(ASYNCIO,
-("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp));
- goto again;
- }
-
- if (bp->b_iocmd == BIO_READ) {
- if (bp->b_rcred == NOCRED && cred != NOCRED)
- bp->b_rcred = crhold(cred);
- } else {
- if (bp->b_wcred == NOCRED && cred != NOCRED)
- bp->b_wcred = crhold(cred);
- }
-
- if (bp->b_flags & B_REMFREE)
- bremfreef(bp);
- BUF_KERNPROC(bp);
- TAILQ_INSERT_TAIL(&nmp->nm_bufq, bp, b_freelist);
- nmp->nm_bufqlen++;
- if ((bp->b_flags & B_DIRECT) && bp->b_iocmd == BIO_WRITE) {
- mtx_lock(&(VTONFS(bp->b_vp))->n_mtx);
- VTONFS(bp->b_vp)->n_flag |= NMODIFIED;
- VTONFS(bp->b_vp)->n_directio_asyncwr++;
- mtx_unlock(&(VTONFS(bp->b_vp))->n_mtx);
- }
- mtx_unlock(&nfs_iod_mtx);
- return (0);
- }
-
- mtx_unlock(&nfs_iod_mtx);
-
- /*
- * All the iods are busy on other mounts, so return EIO to
- * force the caller to process the i/o synchronously.
- */
- NFS_DPF(ASYNCIO, ("nfs_asyncio: no iods available, i/o is synchronous\n"));
- return (EIO);
-}
-
-void
-nfs_doio_directwrite(struct buf *bp)
-{
- int iomode, must_commit;
- struct uio *uiop = (struct uio *)bp->b_caller1;
- char *iov_base = uiop->uio_iov->iov_base;
- struct nfsmount *nmp = VFSTONFS(bp->b_vp->v_mount);
-
- iomode = NFSV3WRITE_FILESYNC;
- uiop->uio_td = NULL; /* NULL since we're in nfsiod */
- (nmp->nm_rpcops->nr_writerpc)(bp->b_vp, uiop, bp->b_wcred, &iomode, &must_commit);
- KASSERT((must_commit == 0), ("nfs_doio_directwrite: Did not commit write"));
- free(iov_base, M_NFSDIRECTIO);
- free(uiop->uio_iov, M_NFSDIRECTIO);
- free(uiop, M_NFSDIRECTIO);
- if ((bp->b_flags & B_DIRECT) && bp->b_iocmd == BIO_WRITE) {
- struct nfsnode *np = VTONFS(bp->b_vp);
- mtx_lock(&np->n_mtx);
- np->n_directio_asyncwr--;
- if (np->n_directio_asyncwr == 0) {
- VTONFS(bp->b_vp)->n_flag &= ~NMODIFIED;
- if ((np->n_flag & NFSYNCWAIT)) {
- np->n_flag &= ~NFSYNCWAIT;
- wakeup((caddr_t)&np->n_directio_asyncwr);
- }
- }
- mtx_unlock(&np->n_mtx);
- }
- bp->b_vp = NULL;
- relpbuf(bp, &nfs_pbuf_freecnt);
-}
-
-/*
- * Do an I/O operation to/from a cache block. This may be called
- * synchronously or from an nfsiod.
- */
-int
-nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td)
-{
- struct uio *uiop;
- struct nfsnode *np;
- struct nfsmount *nmp;
- int error = 0, iomode, must_commit = 0;
- struct uio uio;
- struct iovec io;
- struct proc *p = td ? td->td_proc : NULL;
- uint8_t iocmd;
-
- np = VTONFS(vp);
- nmp = VFSTONFS(vp->v_mount);
- uiop = &uio;
- uiop->uio_iov = &io;
- uiop->uio_iovcnt = 1;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = td;
-
- /*
- * clear BIO_ERROR and B_INVAL state prior to initiating the I/O. We
- * do this here so we do not have to do it in all the code that
- * calls us.
- */
- bp->b_flags &= ~B_INVAL;
- bp->b_ioflags &= ~BIO_ERROR;
-
- KASSERT(!(bp->b_flags & B_DONE), ("nfs_doio: bp %p already marked done", bp));
- iocmd = bp->b_iocmd;
- if (iocmd == BIO_READ) {
- io.iov_len = uiop->uio_resid = bp->b_bcount;
- io.iov_base = bp->b_data;
- uiop->uio_rw = UIO_READ;
-
- switch (vp->v_type) {
- case VREG:
- uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
- nfsstats.read_bios++;
- error = (nmp->nm_rpcops->nr_readrpc)(vp, uiop, cr);
-
- if (!error) {
- if (uiop->uio_resid) {
- /*
- * If we had a short read with no error, we must have
- * hit a file hole. We should zero-fill the remainder.
- * This can also occur if the server hits the file EOF.
- *
- * Holes used to be able to occur due to pending
- * writes, but that is not possible any longer.
- */
- int nread = bp->b_bcount - uiop->uio_resid;
- int left = uiop->uio_resid;
-
- if (left > 0)
- bzero((char *)bp->b_data + nread, left);
- uiop->uio_resid = 0;
- }
- }
- /* ASSERT_VOP_LOCKED(vp, "nfs_doio"); */
- if (p && (vp->v_vflag & VV_TEXT)) {
- mtx_lock(&np->n_mtx);
- if (NFS_TIMESPEC_COMPARE(&np->n_mtime, &np->n_vattr.va_mtime)) {
- mtx_unlock(&np->n_mtx);
- PROC_LOCK(p);
- killproc(p, "text file modification");
- PROC_UNLOCK(p);
- } else
- mtx_unlock(&np->n_mtx);
- }
- break;
- case VLNK:
- uiop->uio_offset = (off_t)0;
- nfsstats.readlink_bios++;
- error = (nmp->nm_rpcops->nr_readlinkrpc)(vp, uiop, cr);
- break;
- case VDIR:
- nfsstats.readdir_bios++;
- uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
- if ((nmp->nm_flag & NFSMNT_RDIRPLUS) != 0) {
- error = nfs_readdirplusrpc(vp, uiop, cr);
- if (error == NFSERR_NOTSUPP)
- nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
- }
- if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
- error = nfs_readdirrpc(vp, uiop, cr);
- /*
- * end-of-directory sets B_INVAL but does not generate an
- * error.
- */
- if (error == 0 && uiop->uio_resid == bp->b_bcount)
- bp->b_flags |= B_INVAL;
- break;
- default:
- nfs_printf("nfs_doio: type %x unexpected\n", vp->v_type);
- break;
- };
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- bp->b_error = error;
- }
- } else {
- /*
- * If we only need to commit, try to commit
- */
- if (bp->b_flags & B_NEEDCOMMIT) {
- int retv;
- off_t off;
-
- off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
- retv = (nmp->nm_rpcops->nr_commit)(
- vp, off, bp->b_dirtyend-bp->b_dirtyoff,
- bp->b_wcred, td);
- if (retv == 0) {
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- bp->b_resid = 0;
- bufdone(bp);
- return (0);
- }
- if (retv == NFSERR_STALEWRITEVERF) {
- nfs_clearcommit(vp->v_mount);
- }
- }
-
- /*
- * Setup for actual write
- */
- mtx_lock(&np->n_mtx);
- if ((off_t)bp->b_blkno * DEV_BSIZE + bp->b_dirtyend > np->n_size)
- bp->b_dirtyend = np->n_size - (off_t)bp->b_blkno * DEV_BSIZE;
- mtx_unlock(&np->n_mtx);
-
- if (bp->b_dirtyend > bp->b_dirtyoff) {
- io.iov_len = uiop->uio_resid = bp->b_dirtyend
- - bp->b_dirtyoff;
- uiop->uio_offset = (off_t)bp->b_blkno * DEV_BSIZE
- + bp->b_dirtyoff;
- io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
- uiop->uio_rw = UIO_WRITE;
- nfsstats.write_bios++;
-
- if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE | B_CLUSTER)) == B_ASYNC)
- iomode = NFSV3WRITE_UNSTABLE;
- else
- iomode = NFSV3WRITE_FILESYNC;
-
- error = (nmp->nm_rpcops->nr_writerpc)(vp, uiop, cr, &iomode, &must_commit);
-
- /*
- * When setting B_NEEDCOMMIT also set B_CLUSTEROK to try
- * to cluster the buffers needing commit. This will allow
- * the system to submit a single commit rpc for the whole
- * cluster. We can do this even if the buffer is not 100%
- * dirty (relative to the NFS blocksize), so we optimize the
- * append-to-file-case.
- *
- * (when clearing B_NEEDCOMMIT, B_CLUSTEROK must also be
- * cleared because write clustering only works for commit
- * rpc's, not for the data portion of the write).
- */
-
- if (!error && iomode == NFSV3WRITE_UNSTABLE) {
- bp->b_flags |= B_NEEDCOMMIT;
- if (bp->b_dirtyoff == 0
- && bp->b_dirtyend == bp->b_bcount)
- bp->b_flags |= B_CLUSTEROK;
- } else {
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
-
- /*
- * For an interrupted write, the buffer is still valid
- * and the write hasn't been pushed to the server yet,
- * so we can't set BIO_ERROR and report the interruption
- * by setting B_EINTR. For the B_ASYNC case, B_EINTR
- * is not relevant, so the rpc attempt is essentially
- * a noop. For the case of a V3 write rpc not being
- * committed to stable storage, the block is still
- * dirty and requires either a commit rpc or another
- * write rpc with iomode == NFSV3WRITE_FILESYNC before
- * the block is reused. This is indicated by setting
- * the B_DELWRI and B_NEEDCOMMIT flags.
- *
- * If the buffer is marked B_PAGING, it does not reside on
- * the vp's paging queues so we cannot call bdirty(). The
- * bp in this case is not an NFS cache block so we should
- * be safe. XXX
- *
- * The logic below breaks up errors into recoverable and
- * unrecoverable. For the former, we clear B_INVAL|B_NOCACHE
- * and keep the buffer around for potential write retries.
- * For the latter (eg ESTALE), we toss the buffer away (B_INVAL)
- * and save the error in the nfsnode. This is less than ideal
- * but necessary. Keeping such buffers around could potentially
- * cause buffer exhaustion eventually (they can never be written
- * out, so will get constantly be re-dirtied). It also causes
- * all sorts of vfs panics. For non-recoverable write errors,
- * also invalidate the attrcache, so we'll be forced to go over
- * the wire for this object, returning an error to user on next
- * call (most of the time).
- */
- if (error == EINTR || error == EIO || error == ETIMEDOUT
- || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
- int s;
-
- s = splbio();
- bp->b_flags &= ~(B_INVAL|B_NOCACHE);
- if ((bp->b_flags & B_PAGING) == 0) {
- bdirty(bp);
- bp->b_flags &= ~B_DONE;
- }
- if (error && (bp->b_flags & B_ASYNC) == 0)
- bp->b_flags |= B_EINTR;
- splx(s);
- } else {
- if (error) {
- bp->b_ioflags |= BIO_ERROR;
- bp->b_flags |= B_INVAL;
- bp->b_error = np->n_error = error;
- mtx_lock(&np->n_mtx);
- np->n_flag |= NWRITEERR;
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- mtx_unlock(&np->n_mtx);
- }
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- }
- } else {
- bp->b_resid = 0;
- bufdone(bp);
- return (0);
- }
- }
- bp->b_resid = uiop->uio_resid;
- if (must_commit)
- nfs_clearcommit(vp->v_mount);
- bufdone(bp);
- return (error);
-}
-
-/*
- * Used to aid in handling ftruncate() operations on the NFS client side.
- * Truncation creates a number of special problems for NFS. We have to
- * throw away VM pages and buffer cache buffers that are beyond EOF, and
- * we have to properly handle VM pages or (potentially dirty) buffers
- * that straddle the truncation point.
- */
-
-int
-nfs_meta_setsize(struct vnode *vp, struct ucred *cred, struct thread *td, u_quad_t nsize)
-{
- struct nfsnode *np = VTONFS(vp);
- u_quad_t tsize;
- int biosize = vp->v_bufobj.bo_bsize;
- int error = 0;
-
- mtx_lock(&np->n_mtx);
- tsize = np->n_size;
- np->n_size = nsize;
- mtx_unlock(&np->n_mtx);
-
- if (nsize < tsize) {
- struct buf *bp;
- daddr_t lbn;
- int bufsize;
-
- /*
- * vtruncbuf() doesn't get the buffer overlapping the
- * truncation point. We may have a B_DELWRI and/or B_CACHE
- * buffer that now needs to be truncated.
- */
- error = vtruncbuf(vp, cred, nsize, biosize);
- lbn = nsize / biosize;
- bufsize = nsize - (lbn * biosize);
- bp = nfs_getcacheblk(vp, lbn, bufsize, td);
- if (!bp)
- return EINTR;
- if (bp->b_dirtyoff > bp->b_bcount)
- bp->b_dirtyoff = bp->b_bcount;
- if (bp->b_dirtyend > bp->b_bcount)
- bp->b_dirtyend = bp->b_bcount;
- bp->b_flags |= B_RELBUF; /* don't leave garbage around */
- brelse(bp);
- } else {
- vnode_pager_setsize(vp, nsize);
- }
- return(error);
-}
-
diff --git a/sys/nfsclient/nfs_kdtrace.c b/sys/nfsclient/nfs_kdtrace.c
deleted file mode 100644
index 429dbc3..0000000
--- a/sys/nfsclient/nfs_kdtrace.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*-
- * Copyright (c) 2009 Robert N. M. Watson
- * All rights reserved.
- *
- * This software was developed at the University of Cambridge Computer
- * Laboratory with support from a grant from Google, Inc.
- *
- * 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-
-#include <sys/dtrace.h>
-#include <sys/dtrace_bsd.h>
-
-#include <nfs/nfsproto.h>
-
-/*
- * dtnfsclient is a DTrace provider that tracks the intent to perform RPCs
- * in the NFS client, as well as acess to and maintenance of the access and
- * attribute caches. This is not quite the same as RPCs, because NFS may
- * issue multiple RPC transactions in the event that authentication fails,
- * there's a jukebox error, or none at all if the access or attribute cache
- * hits. However, it cleanly represents the logical layer between RPC
- * transmission and vnode/vfs operations, providing access to state linking
- * the two.
- */
-
-static int dtnfsclient_unload(void);
-static void dtnfsclient_getargdesc(void *, dtrace_id_t, void *,
- dtrace_argdesc_t *);
-static void dtnfsclient_provide(void *, dtrace_probedesc_t *);
-static void dtnfsclient_destroy(void *, dtrace_id_t, void *);
-static void dtnfsclient_enable(void *, dtrace_id_t, void *);
-static void dtnfsclient_disable(void *, dtrace_id_t, void *);
-static void dtnfsclient_load(void *);
-
-static dtrace_pattr_t dtnfsclient_attr = {
-{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
-};
-
-/*
- * Description of NFSv3 and (optional) NFSv2 probes for a procedure.
- */
-struct dtnfsclient_rpc {
- char *nr_v3_name;
- char *nr_v2_name; /* Or NULL if none. */
-
- /*
- * IDs for the start and done cases, for both NFSv2 and NFSv3.
- */
- uint32_t nr_v2_id_start, nr_v2_id_done;
- uint32_t nr_v3_id_start, nr_v3_id_done;
-};
-
-/*
- * This table is indexed by NFSv3 procedure number, but also used for NFSv2
- * procedure names.
- */
-static struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS] = {
- { "null", "null" },
- { "getattr", "getattr" },
- { "setattr", "setattr" },
- { "lookup", "lookup" },
- { "access" },
- { "readlink", "readlink" },
- { "read", "read" },
- { "write", "write" },
- { "create", "create" },
- { "mkdir", "mkdir" },
- { "symlink", "symlink" },
- { "mknod" },
- { "remove", "remove" },
- { "rmdir", "rmdir" },
- { "rename", "rename" },
- { "link", "link" },
- { "readdir", "readdir" },
- { "readdirplus" },
- { "fsstat", "statfs" },
- { "fsinfo" },
- { "pathconf" },
- { "commit" },
- { "noop" },
-};
-
-/*
- * Module name strings.
- */
-static char *dtnfsclient_accesscache_str = "accesscache";
-static char *dtnfsclient_attrcache_str = "attrcache";
-static char *dtnfsclient_nfs2_str = "nfs2";
-static char *dtnfsclient_nfs3_str = "nfs3";
-
-/*
- * Function name strings.
- */
-static char *dtnfsclient_flush_str = "flush";
-static char *dtnfsclient_load_str = "load";
-static char *dtnfsclient_get_str = "get";
-
-/*
- * Name strings.
- */
-static char *dtnfsclient_done_str = "done";
-static char *dtnfsclient_hit_str = "hit";
-static char *dtnfsclient_miss_str = "miss";
-static char *dtnfsclient_start_str = "start";
-
-static dtrace_pops_t dtnfsclient_pops = {
- dtnfsclient_provide,
- NULL,
- dtnfsclient_enable,
- dtnfsclient_disable,
- NULL,
- NULL,
- dtnfsclient_getargdesc,
- NULL,
- NULL,
- dtnfsclient_destroy
-};
-
-static dtrace_provider_id_t dtnfsclient_id;
-
-/*
- * Most probes are generated from the above RPC table, but for access and
- * attribute caches, we have specific IDs we recognize and handle specially
- * in various spots.
- */
-extern uint32_t nfsclient_accesscache_flush_done_id;
-extern uint32_t nfsclient_accesscache_get_hit_id;
-extern uint32_t nfsclient_accesscache_get_miss_id;
-extern uint32_t nfsclient_accesscache_load_done_id;
-
-extern uint32_t nfsclient_attrcache_flush_done_id;
-extern uint32_t nfsclient_attrcache_get_hit_id;
-extern uint32_t nfsclient_attrcache_get_miss_id;
-extern uint32_t nfsclient_attrcache_load_done_id;
-
-/*
- * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
- * stored in one of these two NFS client-allocated arrays; 0 indicates that
- * the event is not being traced so probes should not be called.
- *
- * For simplicity, we allocate both v2 and v3 arrays as NFS_NPROCS, and the
- * v2 array is simply sparse.
- */
-extern uint32_t nfsclient_nfs2_start_probes[NFS_NPROCS];
-extern uint32_t nfsclient_nfs2_done_probes[NFS_NPROCS];
-
-extern uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS];
-extern uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS];
-
-/*
- * Look up a DTrace probe ID to see if it's associated with a "done" event --
- * if so, we will return a fourth argument type of "int".
- */
-static int
-dtnfs23_isdoneprobe(dtrace_id_t id)
-{
- int i;
-
- for (i = 0; i < NFS_NPROCS; i++) {
- if (dtnfsclient_rpcs[i].nr_v3_id_done == id ||
- dtnfsclient_rpcs[i].nr_v2_id_done == id)
- return (1);
- }
- return (0);
-}
-
-static void
-dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
- dtrace_argdesc_t *desc)
-{
- const char *p = NULL;
-
- if (id == nfsclient_accesscache_flush_done_id ||
- id == nfsclient_attrcache_flush_done_id ||
- id == nfsclient_attrcache_get_miss_id) {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- } else if (id == nfsclient_accesscache_get_hit_id ||
- id == nfsclient_accesscache_get_miss_id) {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- case 1:
- p = "uid_t";
- break;
- case 2:
- p = "uint32_t";
- break;
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- } else if (id == nfsclient_accesscache_load_done_id) {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- case 1:
- p = "uid_t";
- break;
- case 2:
- p = "uint32_t";
- break;
- case 3:
- p = "int";
- break;
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- } else if (id == nfsclient_attrcache_get_hit_id) {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- case 1:
- p = "struct vattr *";
- break;
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- } else if (id == nfsclient_attrcache_load_done_id) {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- case 1:
- p = "struct vattr *";
- break;
- case 2:
- p = "int";
- break;
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- } else {
- switch (desc->dtargd_ndx) {
- case 0:
- p = "struct vnode *";
- break;
- case 1:
- p = "struct mbuf *";
- break;
- case 2:
- p = "struct ucred *";
- break;
- case 3:
- p = "int";
- break;
- case 4:
- if (dtnfs23_isdoneprobe(id)) {
- p = "int";
- break;
- }
- /* FALLSTHROUGH */
- default:
- desc->dtargd_ndx = DTRACE_ARGNONE;
- break;
- }
- }
- if (p != NULL)
- strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
-}
-
-static void
-dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
-{
- int i;
-
- if (desc != NULL)
- return;
-
- /*
- * Register access cache probes.
- */
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
- nfsclient_accesscache_flush_done_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
- nfsclient_accesscache_get_hit_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
- nfsclient_accesscache_get_miss_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
- nfsclient_accesscache_load_done_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_accesscache_str,
- dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
- }
-
- /*
- * Register attribute cache probes.
- */
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
- nfsclient_attrcache_flush_done_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
- nfsclient_attrcache_get_hit_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
- nfsclient_attrcache_get_miss_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
- nfsclient_attrcache_load_done_id = dtrace_probe_create(
- dtnfsclient_id, dtnfsclient_attrcache_str,
- dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
- }
-
- /*
- * Register NFSv2 RPC procedures; note sparseness check for each slot
- * in the NFSv3 procnum-indexed array.
- */
- for (i = 0; i < NFS_NPROCS; i++) {
- if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
- dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
- dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
- 0) {
- dtnfsclient_rpcs[i].nr_v2_id_start =
- dtrace_probe_create(dtnfsclient_id,
- dtnfsclient_nfs2_str,
- dtnfsclient_rpcs[i].nr_v2_name,
- dtnfsclient_start_str, 0,
- &nfsclient_nfs2_start_probes[i]);
- }
- if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
- dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
- dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
- 0) {
- dtnfsclient_rpcs[i].nr_v2_id_done =
- dtrace_probe_create(dtnfsclient_id,
- dtnfsclient_nfs2_str,
- dtnfsclient_rpcs[i].nr_v2_name,
- dtnfsclient_done_str, 0,
- &nfsclient_nfs2_done_probes[i]);
- }
- }
-
- /*
- * Register NFSv3 RPC procedures.
- */
- for (i = 0; i < NFS_NPROCS; i++) {
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
- dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
- 0) {
- dtnfsclient_rpcs[i].nr_v3_id_start =
- dtrace_probe_create(dtnfsclient_id,
- dtnfsclient_nfs3_str,
- dtnfsclient_rpcs[i].nr_v3_name,
- dtnfsclient_start_str, 0,
- &nfsclient_nfs3_start_probes[i]);
- }
- if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
- dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
- 0) {
- dtnfsclient_rpcs[i].nr_v3_id_done =
- dtrace_probe_create(dtnfsclient_id,
- dtnfsclient_nfs3_str,
- dtnfsclient_rpcs[i].nr_v3_name,
- dtnfsclient_done_str, 0,
- &nfsclient_nfs3_done_probes[i]);
- }
- }
-}
-
-static void
-dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
-{
-}
-
-static void
-dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
-{
- uint32_t *p = parg;
- void *f = dtrace_probe;
-
- if (id == nfsclient_accesscache_flush_done_id)
- dtrace_nfsclient_accesscache_flush_done_probe = f;
- else if (id == nfsclient_accesscache_get_hit_id)
- dtrace_nfsclient_accesscache_get_hit_probe = f;
- else if (id == nfsclient_accesscache_get_miss_id)
- dtrace_nfsclient_accesscache_get_miss_probe = f;
- else if (id == nfsclient_accesscache_load_done_id)
- dtrace_nfsclient_accesscache_load_done_probe = f;
- else if (id == nfsclient_attrcache_flush_done_id)
- dtrace_nfsclient_attrcache_flush_done_probe = f;
- else if (id == nfsclient_attrcache_get_hit_id)
- dtrace_nfsclient_attrcache_get_hit_probe = f;
- else if (id == nfsclient_attrcache_get_miss_id)
- dtrace_nfsclient_attrcache_get_miss_probe = f;
- else if (id == nfsclient_attrcache_load_done_id)
- dtrace_nfsclient_attrcache_load_done_probe = f;
- else
- *p = id;
-}
-
-static void
-dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
-{
- uint32_t *p = parg;
-
- if (id == nfsclient_accesscache_flush_done_id)
- dtrace_nfsclient_accesscache_flush_done_probe = NULL;
- else if (id == nfsclient_accesscache_get_hit_id)
- dtrace_nfsclient_accesscache_get_hit_probe = NULL;
- else if (id == nfsclient_accesscache_get_miss_id)
- dtrace_nfsclient_accesscache_get_miss_probe = NULL;
- else if (id == nfsclient_accesscache_load_done_id)
- dtrace_nfsclient_accesscache_load_done_probe = NULL;
- else if (id == nfsclient_attrcache_flush_done_id)
- dtrace_nfsclient_attrcache_flush_done_probe = NULL;
- else if (id == nfsclient_attrcache_get_hit_id)
- dtrace_nfsclient_attrcache_get_hit_probe = NULL;
- else if (id == nfsclient_attrcache_get_miss_id)
- dtrace_nfsclient_attrcache_get_miss_probe = NULL;
- else if (id == nfsclient_attrcache_load_done_id)
- dtrace_nfsclient_attrcache_load_done_probe = NULL;
- else
- *p = 0;
-}
-
-static void
-dtnfsclient_load(void *dummy)
-{
-
- if (dtrace_register("nfsclient", &dtnfsclient_attr,
- DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
- &dtnfsclient_id) != 0)
- return;
-
- dtrace_nfsclient_nfs23_start_probe =
- (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
- dtrace_nfsclient_nfs23_done_probe =
- (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
-}
-
-
-static int
-dtnfsclient_unload()
-{
-
- dtrace_nfsclient_nfs23_start_probe = NULL;
- dtrace_nfsclient_nfs23_done_probe = NULL;
-
- return (dtrace_unregister(dtnfsclient_id));
-}
-
-static int
-dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
-{
- int error = 0;
-
- switch (type) {
- case MOD_LOAD:
- break;
-
- case MOD_UNLOAD:
- break;
-
- case MOD_SHUTDOWN:
- break;
-
- default:
- error = EOPNOTSUPP;
- break;
- }
-
- return (error);
-}
-
-SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
- dtnfsclient_load, NULL);
-SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
- dtnfsclient_unload, NULL);
-
-DEV_MODULE(dtnfsclient, dtnfsclient_modevent, NULL);
-MODULE_VERSION(dtnfsclient, 1);
-MODULE_DEPEND(dtnfsclient, dtrace, 1, 1, 1);
-MODULE_DEPEND(dtnfsclient, opensolaris, 1, 1, 1);
-MODULE_DEPEND(dtnfsclient, oldnfs, 1, 1, 1);
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
deleted file mode 100644
index f88e47f..0000000
--- a/sys/nfsclient/nfs_krpc.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Socket operations for use by nfs
- */
-
-#include "opt_inet6.h"
-#include "opt_kgssapi.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 <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfsclient/nfsm_subs.h>
-#include <nfsclient/nfsmount.h>
-#include <nfsclient/nfsnode.h>
-
-#ifdef KDTRACE_HOOKS
-#include <sys/dtrace_bsd.h>
-
-dtrace_nfsclient_nfs23_start_probe_func_t
- dtrace_nfsclient_nfs23_start_probe;
-
-dtrace_nfsclient_nfs23_done_probe_func_t
- dtrace_nfsclient_nfs23_done_probe;
-
-/*
- * Registered probes by RPC type.
- */
-uint32_t nfsclient_nfs2_start_probes[NFS_NPROCS];
-uint32_t nfsclient_nfs2_done_probes[NFS_NPROCS];
-
-uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS];
-uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS];
-#endif
-
-static int nfs_bufpackets = 4;
-static int nfs_reconnects;
-static int nfs3_jukebox_delay = 10;
-static int nfs_skip_wcc_data_onerr = 1;
-static int fake_wchan;
-
-SYSCTL_DECL(_vfs_oldnfs);
-
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0,
- "Buffer reservation size 2 < x < 64");
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
- "Number of times the nfs client has had to reconnect");
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW,
- &nfs3_jukebox_delay, 0,
- "Number of seconds to delay a retry after receiving EJUKEBOX");
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW,
- &nfs_skip_wcc_data_onerr, 0,
- "Disable weak cache consistency checking when server returns an error");
-
-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);
-
-extern int nfsv2_procid[];
-
-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 */
-};
-
-/*
- * RTT estimator
- */
-
-static enum nfs_rto_timer_t nfs_proct[NFS_NPROCS] = {
- NFS_DEFAULT_TIMER, /* NULL */
- NFS_GETATTR_TIMER, /* GETATTR */
- NFS_DEFAULT_TIMER, /* SETATTR */
- NFS_LOOKUP_TIMER, /* LOOKUP */
- NFS_GETATTR_TIMER, /* ACCESS */
- NFS_READ_TIMER, /* READLINK */
- NFS_READ_TIMER, /* READ */
- NFS_WRITE_TIMER, /* WRITE */
- NFS_DEFAULT_TIMER, /* CREATE */
- NFS_DEFAULT_TIMER, /* MKDIR */
- NFS_DEFAULT_TIMER, /* SYMLINK */
- NFS_DEFAULT_TIMER, /* MKNOD */
- NFS_DEFAULT_TIMER, /* REMOVE */
- NFS_DEFAULT_TIMER, /* RMDIR */
- NFS_DEFAULT_TIMER, /* RENAME */
- NFS_DEFAULT_TIMER, /* LINK */
- NFS_READ_TIMER, /* READDIR */
- NFS_READ_TIMER, /* READDIRPLUS */
- NFS_DEFAULT_TIMER, /* FSSTAT */
- NFS_DEFAULT_TIMER, /* FSINFO */
- NFS_DEFAULT_TIMER, /* PATHCONF */
- NFS_DEFAULT_TIMER, /* COMMIT */
- NFS_DEFAULT_TIMER, /* NOOP */
-};
-
-/*
- * Choose the correct RTT timer for this NFS procedure.
- */
-static inline enum nfs_rto_timer_t
-nfs_rto_timer(u_int32_t procnum)
-{
-
- return (nfs_proct[procnum]);
-}
-
-/*
- * Initialize the RTT estimator state for a new mount point.
- */
-static void
-nfs_init_rtt(struct nfsmount *nmp)
-{
- int i;
-
- for (i = 0; i < NFS_MAX_TIMER; i++) {
- nmp->nm_timers[i].rt_srtt = hz;
- nmp->nm_timers[i].rt_deviate = 0;
- nmp->nm_timers[i].rt_rtxcur = hz;
- }
-}
-
-/*
- * Initialize sockets and congestion for a new NFS connection.
- * We do not free the sockaddr if error.
- */
-int
-nfs_connect(struct nfsmount *nmp)
-{
- int rcvreserve, sndreserve;
- int pktscale;
- struct sockaddr *saddr;
- struct ucred *origcred;
- struct thread *td = curthread;
- CLIENT *client;
- struct netconfig *nconf;
- rpcvers_t vers;
- int one = 1, retries;
- struct timeval timo;
-
- /*
- * 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;
- td->td_ucred = nmp->nm_mountp->mnt_cred;
- saddr = nmp->nm_nam;
-
- vers = NFS_VER2;
- if (nmp->nm_flag & NFSMNT_NFSV3)
- vers = NFS_VER3;
- else if (nmp->nm_flag & NFSMNT_NFSV4)
- vers = NFS_VER4;
- if (saddr->sa_family == AF_INET)
- if (nmp->nm_sotype == SOCK_DGRAM)
- nconf = getnetconfigent("udp");
- else
- nconf = getnetconfigent("tcp");
- else
- if (nmp->nm_sotype == SOCK_DGRAM)
- nconf = getnetconfigent("udp6");
- else
- nconf = getnetconfigent("tcp6");
-
- /*
- * Get buffer reservation size from sysctl, but impose reasonable
- * limits.
- */
- pktscale = nfs_bufpackets;
- if (pktscale < 2)
- pktscale = 2;
- if (pktscale > 64)
- pktscale = 64;
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_sotype == SOCK_DGRAM) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else {
- if (nmp->nm_sotype != SOCK_STREAM)
- panic("nfscon sotype");
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- }
- mtx_unlock(&nmp->nm_mtx);
-
- client = clnt_reconnect_create(nconf, saddr, NFS_PROG, vers,
- sndreserve, rcvreserve);
- CLNT_CONTROL(client, CLSET_WAITCHAN, "nfsreq");
- 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 ((nmp->nm_flag & NFSMNT_SOFT) != 0) {
- 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;
- CLNT_CONTROL(client, CLSET_RETRIES, &retries);
-
- /*
- * 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);
-
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_client) {
- /*
- * Someone else already connected.
- */
- CLNT_RELEASE(client);
- } else
- nmp->nm_client = 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->nm_flag & NFSMNT_NOCONN)) {
- mtx_unlock(&nmp->nm_mtx);
- CLNT_CONTROL(client, CLSET_CONNECT, &one);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- /* Restore current thread's credentials. */
- td->td_ucred = origcred;
-
- mtx_lock(&nmp->nm_mtx);
- /* Initialize other non-zero congestion variables. */
- nfs_init_rtt(nmp);
- mtx_unlock(&nmp->nm_mtx);
- return (0);
-}
-
-/*
- * NFS disconnect. Clean up and unlink.
- */
-void
-nfs_disconnect(struct nfsmount *nmp)
-{
- CLIENT *client;
-
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_client) {
- client = nmp->nm_client;
- nmp->nm_client = NULL;
- mtx_unlock(&nmp->nm_mtx);
- rpc_gss_secpurge_call(client);
- CLNT_CLOSE(client);
- CLNT_RELEASE(client);
- } else
- mtx_unlock(&nmp->nm_mtx);
-}
-
-void
-nfs_safedisconnect(struct nfsmount *nmp)
-{
-
- nfs_disconnect(nmp);
-}
-
-static AUTH *
-nfs_getauth(struct nfsmount *nmp, struct ucred *cred)
-{
- rpc_gss_service_t svc;
- AUTH *auth;
-
- switch (nmp->nm_secflavor) {
- case RPCSEC_GSS_KRB5:
- case RPCSEC_GSS_KRB5I:
- case RPCSEC_GSS_KRB5P:
- if (!nmp->nm_mech_oid)
- if (!rpc_gss_mech_to_oid_call("kerberosv5",
- &nmp->nm_mech_oid))
- return (NULL);
- if (nmp->nm_secflavor == RPCSEC_GSS_KRB5)
- svc = rpc_gss_svc_none;
- else if (nmp->nm_secflavor == RPCSEC_GSS_KRB5I)
- svc = rpc_gss_svc_integrity;
- else
- svc = rpc_gss_svc_privacy;
- auth = rpc_gss_secfind_call(nmp->nm_client, cred,
- nmp->nm_principal, nmp->nm_mech_oid, svc);
- if (auth)
- 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 = time_uptime;
- 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;
- }
-}
-
-/*
- * nfs_request - goes something like this
- * - fill in request struct
- * - links it into list
- * - calls nfs_send() for first transmit
- * - calls nfs_receive() to get reply
- * - break down rpc header and return with nfs reply pointed to
- * by mrep or error
- * nb: always frees up mreq mbuf list
- */
-int
-nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
- struct thread *td, struct ucred *cred, struct mbuf **mrp,
- struct mbuf **mdp, caddr_t *dposp)
-{
- struct mbuf *mrep;
- u_int32_t *tl;
- struct nfsmount *nmp;
- struct mbuf *md;
- time_t waituntil;
- caddr_t dpos;
- int error = 0, timeo;
- AUTH *auth = NULL;
- enum nfs_rto_timer_t timer;
- struct nfs_feedback_arg nf;
- struct rpc_callextra ext;
- enum clnt_stat stat;
- struct timeval timo;
-
- /* Reject requests while attempting a forced unmount. */
- if (vp->v_mount->mnt_kern_flag & MNTK_UNMOUNTF) {
- m_freem(mreq);
- return (ESTALE);
- }
- nmp = VFSTONFS(vp->v_mount);
- bzero(&nf, sizeof(struct nfs_feedback_arg));
- nf.nf_mount = nmp;
- nf.nf_td = td;
- nf.nf_lastmsg = time_uptime -
- ((nmp->nm_tprintf_delay) - (nmp->nm_tprintf_initial_delay));
-
- /*
- * XXX if not already connected call nfs_connect now. Longer
- * term, change nfs_mount to call nfs_connect unconditionally
- * and let clnt_reconnect_create handle reconnects.
- */
- if (!nmp->nm_client)
- nfs_connect(nmp);
-
- auth = nfs_getauth(nmp, cred);
- if (!auth) {
- m_freem(mreq);
- return (EACCES);
- }
- bzero(&ext, sizeof(ext));
- ext.rc_auth = auth;
-
- ext.rc_feedback = nfs_feedback;
- ext.rc_feedback_arg = &nf;
-
- /*
- * Use a conservative timeout for RPCs other than getattr,
- * lookup, read or write. The justification for doing "other"
- * this way is that these RPCs happen so infrequently that
- * timer est. would probably be stale. Also, since many of
- * these RPCs are non-idempotent, a conservative timeout is
- * desired.
- */
- timer = nfs_rto_timer(procnum);
- if (timer != NFS_DEFAULT_TIMER)
- ext.rc_timers = &nmp->nm_timers[timer - 1];
- else
- ext.rc_timers = NULL;
-
-#ifdef KDTRACE_HOOKS
- if (dtrace_nfsclient_nfs23_start_probe != NULL) {
- uint32_t probe_id;
- int probe_procnum;
-
- if (nmp->nm_flag & NFSMNT_NFSV3) {
- probe_id = nfsclient_nfs3_start_probes[procnum];
- probe_procnum = procnum;
- } else {
- probe_id = nfsclient_nfs2_start_probes[procnum];
- probe_procnum = nfsv2_procid[procnum];
- }
- if (probe_id != 0)
- (dtrace_nfsclient_nfs23_start_probe)(probe_id, vp,
- mreq, cred, probe_procnum);
- }
-#endif
-
- nfsstats.rpcrequests++;
-tryagain:
- /*
- * 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->nm_sotype == SOCK_DGRAM) {
- if ((nmp->nm_flag & NFSMNT_SOFT) != 0) {
- /*
- * 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;
- }
- } else {
- timo.tv_sec = nmp->nm_timeo / NFS_HZ;
- timo.tv_usec = (nmp->nm_timeo % NFS_HZ) * 1000000 / NFS_HZ;
- }
- mrep = NULL;
- stat = CLNT_CALL_MBUF(nmp->nm_client, &ext,
- (nmp->nm_flag & NFSMNT_NFSV3) ? procnum : nfsv2_procid[procnum],
- mreq, &mrep, timo);
-
- /*
- * If there was a successful reply and a tprintf msg.
- * tprintf a response.
- */
- if (stat == RPC_SUCCESS)
- error = 0;
- else if (stat == RPC_TIMEDOUT) {
- nfsstats.rpctimeouts++;
- error = ETIMEDOUT;
- } else if (stat == RPC_VERSMISMATCH) {
- nfsstats.rpcinvalid++;
- error = EOPNOTSUPP;
- } else if (stat == RPC_PROGVERSMISMATCH) {
- nfsstats.rpcinvalid++;
- error = EPROTONOSUPPORT;
- } else if (stat == RPC_INTR) {
- error = EINTR;
- } else {
- nfsstats.rpcinvalid++;
- error = EACCES;
- }
- if (error)
- goto nfsmout;
-
- KASSERT(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.
- */
- error = nfs_realign(&mrep, M_NOWAIT);
- if (error == ENOMEM) {
- m_freem(mrep);
- AUTH_DESTROY(auth);
- nfsstats.rpcinvalid++;
- return (error);
- }
-
- md = mrep;
- dpos = mtod(mrep, caddr_t);
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- if (*tl != 0) {
- error = fxdr_unsigned(int, *tl);
- if ((nmp->nm_flag & NFSMNT_NFSV3) &&
- error == NFSERR_TRYLATER) {
- m_freem(mrep);
- error = 0;
- waituntil = time_second + nfs3_jukebox_delay;
- while (time_second < waituntil)
- (void)tsleep(&fake_wchan, PSOCK, "nqnfstry",
- hz);
- goto tryagain;
- }
- /*
- * Make sure NFSERR_RETERR isn't bogusly set by a server
- * such as amd. (No actual NFS error has bit 31 set.)
- */
- error &= ~NFSERR_RETERR;
-
- /*
- * If the File Handle was stale, invalidate the lookup
- * cache, just in case.
- */
- if (error == ESTALE)
- nfs_purgecache(vp);
- /*
- * Skip wcc data on non-ENOENT NFS errors for now.
- * NetApp filers return corrupt postop attrs in the
- * wcc data for NFS err EROFS. Not sure if they could
- * return corrupt postop attrs for others errors.
- * Blocking ENOENT post-op attributes breaks negative
- * name caching, so always allow it through.
- */
- if ((nmp->nm_flag & NFSMNT_NFSV3) &&
- (!nfs_skip_wcc_data_onerr || error == ENOENT)) {
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- error |= NFSERR_RETERR;
- } else
- m_freem(mrep);
- goto nfsmout;
- }
-
-#ifdef KDTRACE_HOOKS
- if (dtrace_nfsclient_nfs23_done_probe != NULL) {
- uint32_t probe_id;
- int probe_procnum;
-
- if (nmp->nm_flag & NFSMNT_NFSV3) {
- probe_id = nfsclient_nfs3_done_probes[procnum];
- probe_procnum = procnum;
- } else {
- probe_id = nfsclient_nfs2_done_probes[procnum];
- probe_procnum = (nmp->nm_flag & NFSMNT_NFSV3) ?
- procnum : nfsv2_procid[procnum];
- }
- if (probe_id != 0)
- (dtrace_nfsclient_nfs23_done_probe)(probe_id, vp,
- mreq, cred, probe_procnum, 0);
- }
-#endif
- m_freem(mreq);
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- AUTH_DESTROY(auth);
- return (0);
-
-nfsmout:
-#ifdef KDTRACE_HOOKS
- if (dtrace_nfsclient_nfs23_done_probe != NULL) {
- uint32_t probe_id;
- int probe_procnum;
-
- if (nmp->nm_flag & NFSMNT_NFSV3) {
- probe_id = nfsclient_nfs3_done_probes[procnum];
- probe_procnum = procnum;
- } else {
- probe_id = nfsclient_nfs2_done_probes[procnum];
- probe_procnum = (nmp->nm_flag & NFSMNT_NFSV3) ?
- procnum : nfsv2_procid[procnum];
- }
- if (probe_id != 0)
- (dtrace_nfsclient_nfs23_done_probe)(probe_id, vp,
- mreq, cred, probe_procnum, error);
- }
-#endif
- m_freem(mreq);
- if (auth)
- AUTH_DESTROY(auth);
- 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
-nfs_nmcancelreqs(struct nfsmount *nmp)
-{
-
- if (nmp->nm_client)
- CLNT_CLOSE(nmp->nm_client);
- 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 nfs_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 < sizeof(nfs_sig_set)/sizeof(int) ; i++)
- if (SIGISMEMBER(set, nfs_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
-nfs_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 < sizeof(nfs_sig_set)/sizeof(int) ; i++) {
- /*
- * But make sure we leave the ones already masked
- * by the process, i.e. remove the signal from the
- * temporary signalmask only if it wasn't already
- * in p_sigmask.
- */
- if (!SIGISMEMBER(td->td_sigmask, nfs_sig_set[i]) &&
- !SIGISMEMBER(p->p_sigacts->ps_sigignore, nfs_sig_set[i]))
- SIGDELSET(newset, nfs_sig_set[i]);
- }
- mtx_unlock(&p->p_sigacts->ps_mtx);
- kern_sigprocmask(td, SIG_SETMASK, &newset, oldset,
- SIGPROCMASK_PROC_LOCKED);
- PROC_UNLOCK(p);
-}
-
-void
-nfs_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
-nfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority,
- char *wmesg, int timo)
-{
- sigset_t oldset;
- int error;
- struct proc *p;
-
- if ((priority & PCATCH) == 0)
- return msleep(ident, mtx, priority, wmesg, timo);
- if (td == NULL)
- td = curthread; /* XXX */
- nfs_set_sigmask(td, &oldset);
- error = msleep(ident, mtx, priority, wmesg, timo);
- nfs_restore_sigmask(td, &oldset);
- p = td->td_proc;
- return (error);
-}
-
-/*
- * Test for a termination condition pending on the process.
- * This is used for NFSMNT_INT mounts.
- */
-int
-nfs_sigintr(struct nfsmount *nmp, struct thread *td)
-{
- struct proc *p;
- sigset_t tmpset;
-
- /* Terminate all requests while attempting a forced unmount. */
- if (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
- 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/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c
deleted file mode 100644
index 2fb2c88..0000000
--- a/sys/nfsclient/nfs_nfsiod.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/namei.h>
-#include <sys/unistd.h>
-#include <sys/kthread.h>
-#include <sys/fcntl.h>
-#include <sys/lockf.h>
-#include <sys/mutex.h>
-#include <sys/taskqueue.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsm_subs.h>
-#include <nfsclient/nfsmount.h>
-#include <nfsclient/nfsnode.h>
-#include <nfs/nfs_lock.h>
-
-static MALLOC_DEFINE(M_NFSSVC, "nfsclient_srvsock", "Nfs server structure");
-
-static void nfssvc_iod(void *);
-
-static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
-
-SYSCTL_DECL(_vfs_oldnfs);
-
-/* Maximum number of seconds a nfsiod kthread will sleep before exiting */
-static unsigned int nfs_iodmaxidle = 120;
-SYSCTL_UINT(_vfs_oldnfs, OID_AUTO, iodmaxidle, CTLFLAG_RW, &nfs_iodmaxidle, 0,
- "Max number of seconds an nfsiod kthread will sleep before exiting");
-
-/* Maximum number of nfsiod kthreads */
-unsigned int nfs_iodmax = 20;
-
-/* Minimum number of nfsiod kthreads to keep as spares */
-static unsigned int nfs_iodmin = 0;
-
-static int nfs_nfsiodnew_sync(void);
-
-static int
-sysctl_iodmin(SYSCTL_HANDLER_ARGS)
-{
- int error, i;
- int newmin;
-
- newmin = nfs_iodmin;
- error = sysctl_handle_int(oidp, &newmin, 0, req);
- if (error || (req->newptr == NULL))
- return (error);
- mtx_lock(&nfs_iod_mtx);
- if (newmin > nfs_iodmax) {
- error = EINVAL;
- goto out;
- }
- nfs_iodmin = newmin;
- if (nfs_numasync >= nfs_iodmin)
- goto out;
- /*
- * If the current number of nfsiod is lower
- * than the new minimum, create some more.
- */
- for (i = nfs_iodmin - nfs_numasync; i > 0; i--)
- nfs_nfsiodnew_sync();
-out:
- mtx_unlock(&nfs_iod_mtx);
- return (0);
-}
-SYSCTL_PROC(_vfs_oldnfs, OID_AUTO, iodmin, CTLTYPE_UINT | CTLFLAG_RW, 0,
- sizeof (nfs_iodmin), sysctl_iodmin, "IU",
- "Min number of nfsiod kthreads to keep as spares");
-
-
-static int
-sysctl_iodmax(SYSCTL_HANDLER_ARGS)
-{
- int error, i;
- int iod, newmax;
-
- newmax = nfs_iodmax;
- error = sysctl_handle_int(oidp, &newmax, 0, req);
- if (error || (req->newptr == NULL))
- return (error);
- if (newmax > NFS_MAXASYNCDAEMON)
- return (EINVAL);
- mtx_lock(&nfs_iod_mtx);
- nfs_iodmax = newmax;
- if (nfs_numasync <= nfs_iodmax)
- goto out;
- /*
- * If there are some asleep nfsiods that should
- * exit, wakeup() them so that they check nfs_iodmax
- * and exit. Those who are active will exit as
- * soon as they finish I/O.
- */
- iod = nfs_numasync - 1;
- for (i = 0; i < nfs_numasync - nfs_iodmax; i++) {
- if (nfs_iodwant[iod] == NFSIOD_AVAILABLE)
- wakeup(&nfs_iodwant[iod]);
- iod--;
- }
-out:
- mtx_unlock(&nfs_iod_mtx);
- return (0);
-}
-SYSCTL_PROC(_vfs_oldnfs, OID_AUTO, iodmax, CTLTYPE_UINT | CTLFLAG_RW, 0,
- sizeof (nfs_iodmax), sysctl_iodmax, "IU",
- "Max number of nfsiod kthreads");
-
-static int
-nfs_nfsiodnew_sync(void)
-{
- int error, i;
-
- mtx_assert(&nfs_iod_mtx, MA_OWNED);
- for (i = 0; i < nfs_iodmax; i++) {
- if (nfs_asyncdaemon[i] == 0) {
- nfs_asyncdaemon[i] = 1;
- break;
- }
- }
- if (i == nfs_iodmax)
- return (0);
- mtx_unlock(&nfs_iod_mtx);
- error = kproc_create(nfssvc_iod, nfs_asyncdaemon + i, NULL,
- RFHIGHPID, 0, "nfsiod %d", i);
- mtx_lock(&nfs_iod_mtx);
- if (error == 0) {
- nfs_numasync++;
- nfs_iodwant[i] = NFSIOD_AVAILABLE;
- } else
- nfs_asyncdaemon[i] = 0;
- return (error);
-}
-
-void
-nfs_nfsiodnew_tq(__unused void *arg, int pending)
-{
-
- mtx_lock(&nfs_iod_mtx);
- while (pending > 0) {
- pending--;
- nfs_nfsiodnew_sync();
- }
- mtx_unlock(&nfs_iod_mtx);
-}
-
-void
-nfs_nfsiodnew(void)
-{
-
- mtx_assert(&nfs_iod_mtx, MA_OWNED);
- taskqueue_enqueue(taskqueue_thread, &nfs_nfsiodnew_task);
-}
-
-static void
-nfsiod_setup(void *dummy)
-{
- int error;
-
- TUNABLE_INT_FETCH("vfs.oldnfs.iodmin", &nfs_iodmin);
- mtx_lock(&nfs_iod_mtx);
- /* Silently limit the start number of nfsiod's */
- if (nfs_iodmin > NFS_MAXASYNCDAEMON)
- nfs_iodmin = NFS_MAXASYNCDAEMON;
-
- while (nfs_numasync < nfs_iodmin) {
- error = nfs_nfsiodnew_sync();
- if (error == -1)
- panic("nfsiod_setup: nfs_nfsiodnew failed");
- }
- mtx_unlock(&nfs_iod_mtx);
-}
-SYSINIT(nfsiod, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, nfsiod_setup, NULL);
-
-static int nfs_defect = 0;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0,
- "Allow nfsiods to migrate serving different mounts");
-
-/*
- * Asynchronous I/O daemons for client nfs.
- * They do read-ahead and write-behind operations on the block I/O cache.
- * Returns if we hit the timeout defined by the iodmaxidle sysctl.
- */
-static void
-nfssvc_iod(void *instance)
-{
- struct buf *bp;
- struct nfsmount *nmp;
- int myiod, timo;
- int error = 0;
-
- mtx_lock(&nfs_iod_mtx);
- myiod = (int *)instance - nfs_asyncdaemon;
- /*
- * Main loop
- */
- for (;;) {
- while (((nmp = nfs_iodmount[myiod]) == NULL)
- || !TAILQ_FIRST(&nmp->nm_bufq)) {
- if (myiod >= nfs_iodmax)
- goto finish;
- if (nmp)
- nmp->nm_bufqiods--;
- if (nfs_iodwant[myiod] == NFSIOD_NOT_AVAILABLE)
- nfs_iodwant[myiod] = NFSIOD_AVAILABLE;
- nfs_iodmount[myiod] = NULL;
- /*
- * Always keep at least nfs_iodmin kthreads.
- */
- timo = (myiod < nfs_iodmin) ? 0 : nfs_iodmaxidle * hz;
- error = msleep(&nfs_iodwant[myiod], &nfs_iod_mtx, PWAIT | PCATCH,
- "-", timo);
- if (error) {
- nmp = nfs_iodmount[myiod];
- /*
- * Rechecking the nm_bufq closes a rare race where the
- * nfsiod is woken up at the exact time the idle timeout
- * fires
- */
- if (nmp && TAILQ_FIRST(&nmp->nm_bufq))
- error = 0;
- break;
- }
- }
- if (error)
- break;
- while ((bp = TAILQ_FIRST(&nmp->nm_bufq)) != NULL) {
- int giant_locked = 0;
-
- /* Take one off the front of the list */
- TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist);
- nmp->nm_bufqlen--;
- if (nmp->nm_bufqwant && nmp->nm_bufqlen <= nfs_numasync) {
- nmp->nm_bufqwant = 0;
- wakeup(&nmp->nm_bufq);
- }
- mtx_unlock(&nfs_iod_mtx);
- if (NFS_ISV4(bp->b_vp)) {
- giant_locked = 1;
- mtx_lock(&Giant);
- }
- if (bp->b_flags & B_DIRECT) {
- KASSERT((bp->b_iocmd == BIO_WRITE), ("nfscvs_iod: BIO_WRITE not set"));
- (void)nfs_doio_directwrite(bp);
- } else {
- if (bp->b_iocmd == BIO_READ)
- (void) nfs_doio(bp->b_vp, bp, bp->b_rcred, NULL);
- else
- (void) nfs_doio(bp->b_vp, bp, bp->b_wcred, NULL);
- }
- if (giant_locked)
- mtx_unlock(&Giant);
- mtx_lock(&nfs_iod_mtx);
- /*
- * Make sure the nmp hasn't been dismounted as soon as
- * nfs_doio() completes for the last buffer.
- */
- nmp = nfs_iodmount[myiod];
- if (nmp == NULL)
- break;
-
- /*
- * If there are more than one iod on this mount, then defect
- * so that the iods can be shared out fairly between the mounts
- */
- if (nfs_defect && nmp->nm_bufqiods > 1) {
- NFS_DPF(ASYNCIO,
- ("nfssvc_iod: iod %d defecting from mount %p\n",
- myiod, nmp));
- nfs_iodmount[myiod] = NULL;
- nmp->nm_bufqiods--;
- break;
- }
- }
- }
-finish:
- nfs_asyncdaemon[myiod] = 0;
- if (nmp)
- nmp->nm_bufqiods--;
- nfs_iodwant[myiod] = NFSIOD_NOT_AVAILABLE;
- nfs_iodmount[myiod] = NULL;
- /* Someone may be waiting for the last nfsiod to terminate. */
- if (--nfs_numasync == 0)
- wakeup(&nfs_numasync);
- mtx_unlock(&nfs_iod_mtx);
- if ((error == 0) || (error == EWOULDBLOCK))
- kproc_exit(0);
- /* Abnormal termination */
- kproc_exit(1);
-}
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
deleted file mode 100644
index cee4343..0000000
--- a/sys/nfsclient/nfs_node.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/fnv_hash.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/taskqueue.h>
-#include <sys/vnode.h>
-
-#include <vm/uma.h>
-
-#include <nfs/nfsproto.h>
-#include <nfs/nfs_lock.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsnode.h>
-#include <nfsclient/nfsmount.h>
-
-static uma_zone_t nfsnode_zone;
-
-static void nfs_freesillyrename(void *arg, __unused int pending);
-
-#define TRUE 1
-#define FALSE 0
-
-void
-nfs_nhinit(void)
-{
-
- nfsnode_zone = uma_zcreate("NFSNODE", sizeof(struct nfsnode), NULL,
- NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
-}
-
-void
-nfs_nhuninit(void)
-{
- uma_zdestroy(nfsnode_zone);
-}
-
-struct nfs_vncmp {
- int fhsize;
- void *fh;
-};
-
-static int
-nfs_vncmpf(struct vnode *vp, void *arg)
-{
- struct nfs_vncmp *a;
- struct nfsnode *np;
-
- a = arg;
- np = VTONFS(vp);
- return (bcmp(a->fh, np->n_fhp, a->fhsize));
-}
-
-/*
- * Look up a vnode/nfsnode by file handle.
- * Callers must check for mount points!!
- * In all cases, a pointer to a
- * nfsnode structure is returned.
- */
-int
-nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int flags)
-{
- struct thread *td = curthread; /* XXX */
- struct nfsnode *np;
- struct vnode *vp;
- struct vnode *nvp;
- int error;
- u_int hash;
- struct nfsmount *nmp;
- struct nfs_vncmp ncmp;
-
- nmp = VFSTONFS(mntp);
- *npp = NULL;
-
- hash = fnv_32_buf(fhp->fh_bytes, fhsize, FNV1_32_INIT);
- ncmp.fhsize = fhsize;
- ncmp.fh = fhp;
-
- error = vfs_hash_get(mntp, hash, flags,
- td, &nvp, nfs_vncmpf, &ncmp);
- if (error)
- return (error);
- if (nvp != NULL) {
- *npp = VTONFS(nvp);
- return (0);
- }
- np = uma_zalloc(nfsnode_zone, M_WAITOK | M_ZERO);
-
- error = getnewvnode("nfs", mntp, &nfs_vnodeops, &nvp);
- if (error) {
- uma_zfree(nfsnode_zone, np);
- return (error);
- }
- vp = nvp;
- vp->v_bufobj.bo_ops = &buf_ops_nfs;
- vp->v_data = np;
- np->n_vnode = vp;
- /*
- * Initialize the mutex even if the vnode is going to be a loser.
- * This simplifies the logic in reclaim, which can then unconditionally
- * destroy the mutex (in the case of the loser, or if hash_insert happened
- * to return an error no special casing is needed).
- */
- mtx_init(&np->n_mtx, "NFSnode lock", NULL, MTX_DEF);
- /*
- * NFS supports recursive and shared locking.
- */
- lockmgr(vp->v_vnlock, LK_EXCLUSIVE | LK_NOWITNESS, NULL);
- VN_LOCK_AREC(vp);
- VN_LOCK_ASHARE(vp);
- if (fhsize > NFS_SMALLFH) {
- np->n_fhp = malloc(fhsize, M_NFSBIGFH, M_WAITOK);
- } else
- np->n_fhp = &np->n_fh;
- bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
- np->n_fhsize = fhsize;
- error = insmntque(vp, mntp);
- if (error != 0) {
- *npp = NULL;
- if (np->n_fhsize > NFS_SMALLFH) {
- free((caddr_t)np->n_fhp, M_NFSBIGFH);
- }
- mtx_destroy(&np->n_mtx);
- uma_zfree(nfsnode_zone, np);
- return (error);
- }
- error = vfs_hash_insert(vp, hash, flags,
- td, &nvp, nfs_vncmpf, &ncmp);
- if (error)
- return (error);
- if (nvp != NULL) {
- *npp = VTONFS(nvp);
- /* vfs_hash_insert() vput()'s the losing vnode */
- return (0);
- }
- *npp = np;
-
- return (0);
-}
-
-/*
- * Do the vrele(sp->s_dvp) as a separate task in order to avoid a
- * deadlock because of a LOR when vrele() locks the directory vnode.
- */
-static void
-nfs_freesillyrename(void *arg, __unused int pending)
-{
- struct sillyrename *sp;
-
- sp = arg;
- vrele(sp->s_dvp);
- free(sp, M_NFSREQ);
-}
-
-int
-nfs_inactive(struct vop_inactive_args *ap)
-{
- struct nfsnode *np;
- struct sillyrename *sp;
- struct thread *td = curthread; /* XXX */
-
- np = VTONFS(ap->a_vp);
- mtx_lock(&np->n_mtx);
- if (ap->a_vp->v_type != VDIR) {
- sp = np->n_sillyrename;
- np->n_sillyrename = NULL;
- } else
- sp = NULL;
- if (sp) {
- mtx_unlock(&np->n_mtx);
- (void)nfs_vinvalbuf(ap->a_vp, 0, td, 1);
- /*
- * Remove the silly file that was rename'd earlier
- */
- (sp->s_removeit)(sp);
- crfree(sp->s_cred);
- TASK_INIT(&sp->s_task, 0, nfs_freesillyrename, sp);
- taskqueue_enqueue(taskqueue_thread, &sp->s_task);
- mtx_lock(&np->n_mtx);
- }
- np->n_flag &= NMODIFIED;
- mtx_unlock(&np->n_mtx);
- return (0);
-}
-
-/*
- * Reclaim an nfsnode so that it can be used for other purposes.
- */
-int
-nfs_reclaim(struct vop_reclaim_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct nfsdmap *dp, *dp2;
-
- /*
- * If the NLM is running, give it a chance to abort pending
- * locks.
- */
- if (nfs_reclaim_p)
- nfs_reclaim_p(ap);
-
- /*
- * Destroy the vm object and flush associated pages.
- */
- vnode_destroy_vobject(vp);
-
- vfs_hash_remove(vp);
-
- /*
- * Free up any directory cookie structures and
- * large file handle structures that might be associated with
- * this nfs node.
- */
- if (vp->v_type == VDIR) {
- dp = LIST_FIRST(&np->n_cookies);
- while (dp) {
- dp2 = dp;
- dp = LIST_NEXT(dp, ndm_list);
- free((caddr_t)dp2, M_NFSDIROFF);
- }
- }
- if (np->n_writecred != NULL)
- crfree(np->n_writecred);
- if (np->n_fhsize > NFS_SMALLFH) {
- free((caddr_t)np->n_fhp, M_NFSBIGFH);
- }
- mtx_destroy(&np->n_mtx);
- uma_zfree(nfsnode_zone, vp->v_data);
- vp->v_data = NULL;
- return (0);
-}
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
deleted file mode 100644
index d4fd5eb..0000000
--- a/sys/nfsclient/nfs_subs.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * These functions support the macros and help fiddle mbuf chains for
- * the nfs op functions. They do things like create the rpc header and
- * copy data between mbuf chains and uio lists.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/namei.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/malloc.h>
-#include <sys/rwlock.h>
-#include <sys/sysent.h>
-#include <sys/syscall.h>
-#include <sys/sysproto.h>
-#include <sys/taskqueue.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
-#include <vm/uma.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsnode.h>
-#include <nfs/nfs_kdtrace.h>
-#include <nfs/xdr_subs.h>
-#include <nfsclient/nfsm_subs.h>
-#include <nfsclient/nfsmount.h>
-
-#include <netinet/in.h>
-
-/*
- * Note that stdarg.h and the ANSI style va_start macro is used for both
- * ANSI and traditional C compilers.
- */
-#include <machine/stdarg.h>
-
-#ifdef KDTRACE_HOOKS
-dtrace_nfsclient_attrcache_flush_probe_func_t
- dtrace_nfsclient_attrcache_flush_done_probe;
-uint32_t nfsclient_attrcache_flush_done_id;
-
-dtrace_nfsclient_attrcache_get_hit_probe_func_t
- dtrace_nfsclient_attrcache_get_hit_probe;
-uint32_t nfsclient_attrcache_get_hit_id;
-
-dtrace_nfsclient_attrcache_get_miss_probe_func_t
- dtrace_nfsclient_attrcache_get_miss_probe;
-uint32_t nfsclient_attrcache_get_miss_id;
-
-dtrace_nfsclient_attrcache_load_probe_func_t
- dtrace_nfsclient_attrcache_load_done_probe;
-uint32_t nfsclient_attrcache_load_done_id;
-#endif /* !KDTRACE_HOOKS */
-
-/*
- * Data items converted to xdr at startup, since they are constant
- * This is kinda hokey, but may save a little time doing byte swaps
- */
-u_int32_t nfs_xdrneg1;
-u_int32_t nfs_true, nfs_false;
-
-/* And other global data */
-static u_int32_t nfs_xid = 0;
-static enum vtype nv2tov_type[8]= {
- VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON
-};
-
-int nfs_ticks;
-int nfs_pbuf_freecnt = -1; /* start out unlimited */
-
-struct nfs_bufq nfs_bufq;
-static struct mtx nfs_xid_mtx;
-struct task nfs_nfsiodnew_task;
-
-/*
- * and the reverse mapping from generic to Version 2 procedure numbers
- */
-int nfsv2_procid[NFS_NPROCS] = {
- 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,
- NFSV2PROC_NOOP,
-};
-
-LIST_HEAD(nfsnodehashhead, nfsnode);
-
-u_int32_t
-nfs_xid_gen(void)
-{
- uint32_t xid;
-
- mtx_lock(&nfs_xid_mtx);
-
- /* Get a pretty random xid to start with */
- if (!nfs_xid)
- nfs_xid = random();
- /*
- * Skip zero xid if it should ever happen.
- */
- if (++nfs_xid == 0)
- nfs_xid++;
- xid = nfs_xid;
- mtx_unlock(&nfs_xid_mtx);
- return xid;
-}
-
-/*
- * copies a uio scatter/gather list to an mbuf chain.
- * NOTE: can ony handle iovcnt == 1
- */
-int
-nfsm_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos)
-{
- char *uiocp;
- struct mbuf *mp, *mp2;
- int xfer, left, mlen;
- int uiosiz, clflg, rem;
- char *cp;
-
- KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
-
- if (siz > MLEN) /* or should it >= MCLBYTES ?? */
- clflg = 1;
- else
- clflg = 0;
- rem = nfsm_rndup(siz)-siz;
- mp = mp2 = *mq;
- while (siz > 0) {
- left = uiop->uio_iov->iov_len;
- uiocp = uiop->uio_iov->iov_base;
- if (left > siz)
- left = siz;
- uiosiz = left;
- while (left > 0) {
- mlen = M_TRAILINGSPACE(mp);
- if (mlen == 0) {
- if (clflg)
- mp = m_getcl(M_WAITOK, MT_DATA, 0);
- else
- mp = m_get(M_WAITOK, MT_DATA);
- mp2->m_next = mp;
- mp2 = mp;
- mlen = M_TRAILINGSPACE(mp);
- }
- xfer = (left > mlen) ? mlen : left;
-#ifdef notdef
- /* Not Yet.. */
- if (uiop->uio_iov->iov_op != NULL)
- (*(uiop->uio_iov->iov_op))
- (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
-#endif
- if (uiop->uio_segflg == UIO_SYSSPACE)
- bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- else
- copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
- mp->m_len += xfer;
- left -= xfer;
- uiocp += xfer;
- uiop->uio_offset += xfer;
- uiop->uio_resid -= xfer;
- }
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + uiosiz;
- uiop->uio_iov->iov_len -= uiosiz;
- siz -= uiosiz;
- }
- if (rem > 0) {
- if (rem > M_TRAILINGSPACE(mp)) {
- mp = m_get(M_WAITOK, MT_DATA);
- mp2->m_next = mp;
- }
- cp = mtod(mp, caddr_t)+mp->m_len;
- for (left = 0; left < rem; left++)
- *cp++ = '\0';
- mp->m_len += rem;
- *bpos = cp;
- } else
- *bpos = mtod(mp, caddr_t)+mp->m_len;
- *mq = mp;
- return (0);
-}
-
-/*
- * Copy a string into mbufs for the hard cases...
- */
-int
-nfsm_strtmbuf(struct mbuf **mb, char **bpos, const char *cp, long siz)
-{
- struct mbuf *m1 = NULL, *m2;
- long left, xfer, len, tlen;
- u_int32_t *tl;
- int putsize;
-
- putsize = 1;
- m2 = *mb;
- left = M_TRAILINGSPACE(m2);
- if (left > 0) {
- tl = ((u_int32_t *)(*bpos));
- *tl++ = txdr_unsigned(siz);
- putsize = 0;
- left -= NFSX_UNSIGNED;
- m2->m_len += NFSX_UNSIGNED;
- if (left > 0) {
- bcopy(cp, (caddr_t) tl, left);
- siz -= left;
- cp += left;
- m2->m_len += left;
- left = 0;
- }
- }
- /* Loop around adding mbufs */
- while (siz > 0) {
- if (siz > MLEN) {
- m1 = m_getcl(M_WAITOK, MT_DATA, 0);
- m1->m_len = MCLBYTES;
- } else {
- m1 = m_get(M_WAITOK, MT_DATA);
- m1->m_len = MLEN;
- }
- m2->m_next = m1;
- m2 = m1;
- tl = mtod(m1, u_int32_t *);
- tlen = 0;
- if (putsize) {
- *tl++ = txdr_unsigned(siz);
- m1->m_len -= NFSX_UNSIGNED;
- tlen = NFSX_UNSIGNED;
- putsize = 0;
- }
- if (siz < m1->m_len) {
- len = nfsm_rndup(siz);
- xfer = siz;
- if (xfer < len)
- *(tl+(xfer>>2)) = 0;
- } else {
- xfer = len = m1->m_len;
- }
- bcopy(cp, (caddr_t) tl, xfer);
- m1->m_len = len+tlen;
- siz -= xfer;
- cp += xfer;
- }
- *mb = m1;
- *bpos = mtod(m1, caddr_t)+m1->m_len;
- return (0);
-}
-
-/*
- * Called once to initialize data structures...
- */
-int
-nfs_init(struct vfsconf *vfsp)
-{
- int i;
-
- nfsmount_zone = uma_zcreate("NFSMOUNT", sizeof(struct nfsmount),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- nfs_true = txdr_unsigned(TRUE);
- nfs_false = txdr_unsigned(FALSE);
- nfs_xdrneg1 = txdr_unsigned(-1);
- nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
- if (nfs_ticks < 1)
- nfs_ticks = 1;
- /* Ensure async daemons disabled */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
- nfs_iodwant[i] = NFSIOD_NOT_AVAILABLE;
- nfs_iodmount[i] = NULL;
- }
- nfs_nhinit(); /* Init the nfsnode table */
-
- /*
- * Initialize reply list and start timer
- */
- mtx_init(&nfs_iod_mtx, "NFS iod lock", NULL, MTX_DEF);
- mtx_init(&nfs_xid_mtx, "NFS xid lock", NULL, MTX_DEF);
- TASK_INIT(&nfs_nfsiodnew_task, 0, nfs_nfsiodnew_tq, NULL);
-
- nfs_pbuf_freecnt = nswbuf / 2 + 1;
-
- return (0);
-}
-
-int
-nfs_uninit(struct vfsconf *vfsp)
-{
- int i;
-
- /*
- * Tell all nfsiod processes to exit. Clear nfs_iodmax, and wakeup
- * any sleeping nfsiods so they check nfs_iodmax and exit.
- * Drain nfsiodnew task before we wait for them to finish.
- */
- mtx_lock(&nfs_iod_mtx);
- nfs_iodmax = 0;
- mtx_unlock(&nfs_iod_mtx);
- taskqueue_drain(taskqueue_thread, &nfs_nfsiodnew_task);
- mtx_lock(&nfs_iod_mtx);
- for (i = 0; i < nfs_numasync; i++)
- if (nfs_iodwant[i] == NFSIOD_AVAILABLE)
- wakeup(&nfs_iodwant[i]);
- /* The last nfsiod to exit will wake us up when nfs_numasync hits 0 */
- while (nfs_numasync)
- msleep(&nfs_numasync, &nfs_iod_mtx, PWAIT, "ioddie", 0);
- mtx_unlock(&nfs_iod_mtx);
- nfs_nhuninit();
- uma_zdestroy(nfsmount_zone);
- return (0);
-}
-
-void
-nfs_dircookie_lock(struct nfsnode *np)
-{
- mtx_lock(&np->n_mtx);
- while (np->n_flag & NDIRCOOKIELK)
- (void) msleep(&np->n_flag, &np->n_mtx, PZERO, "nfsdirlk", 0);
- np->n_flag |= NDIRCOOKIELK;
- mtx_unlock(&np->n_mtx);
-}
-
-void
-nfs_dircookie_unlock(struct nfsnode *np)
-{
- mtx_lock(&np->n_mtx);
- np->n_flag &= ~NDIRCOOKIELK;
- wakeup(&np->n_flag);
- mtx_unlock(&np->n_mtx);
-}
-
-int
-nfs_upgrade_vnlock(struct vnode *vp)
-{
- int old_lock;
-
- ASSERT_VOP_LOCKED(vp, "nfs_upgrade_vnlock");
- old_lock = VOP_ISLOCKED(vp);
- if (old_lock != LK_EXCLUSIVE) {
- KASSERT(old_lock == LK_SHARED,
- ("nfs_upgrade_vnlock: wrong old_lock %d", old_lock));
- /* Upgrade to exclusive lock, this might block */
- vn_lock(vp, LK_UPGRADE | LK_RETRY);
- }
- return (old_lock);
-}
-
-void
-nfs_downgrade_vnlock(struct vnode *vp, int old_lock)
-{
- if (old_lock != LK_EXCLUSIVE) {
- KASSERT(old_lock == LK_SHARED, ("wrong old_lock %d", old_lock));
- /* Downgrade from exclusive lock. */
- vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
- }
-}
-
-void
-nfs_printf(const char *fmt, ...)
-{
- va_list ap;
-
- mtx_lock(&Giant);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- mtx_unlock(&Giant);
-}
-
-/*
- * Attribute cache routines.
- * nfs_loadattrcache() - loads or updates the cache contents from attributes
- * that are on the mbuf list
- * nfs_getattrcache() - returns valid attributes if found in cache, returns
- * error otherwise
- */
-
-/*
- * Load the attribute cache (that lives in the nfsnode entry) with
- * the values on the mbuf list and
- * Iff vap not NULL
- * copy the attributes to *vaper
- */
-int
-nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
- struct vattr *vaper, int dontshrink)
-{
- struct vnode *vp = *vpp;
- struct vattr *vap;
- struct nfs_fattr *fp;
- struct nfsnode *np = NULL;
- int32_t t1;
- caddr_t cp2;
- int rdev;
- struct mbuf *md;
- enum vtype vtyp;
- u_short vmode;
- struct timespec mtime, mtime_save;
- int v3 = NFS_ISV3(vp);
- int error = 0;
- u_quad_t nsize;
- int setnsize;
-
- md = *mdp;
- t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
- cp2 = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, M_WAITOK);
- if (cp2 == NULL) {
- error = EBADRPC;
- goto out;
- }
- fp = (struct nfs_fattr *)cp2;
- if (v3) {
- vtyp = nfsv3tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- rdev = makedev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
- fxdr_unsigned(int, fp->fa3_rdev.specdata2));
- fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
- } else {
- vtyp = nfsv2tov_type(fp->fa_type);
- vmode = fxdr_unsigned(u_short, fp->fa_mode);
- /*
- * XXX
- *
- * The duplicate information returned in fa_type and fa_mode
- * is an ambiguity in the NFS version 2 protocol.
- *
- * VREG should be taken literally as a regular file. If a
- * server intents to return some type information differently
- * in the upper bits of the mode field (e.g. for sockets, or
- * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we
- * leave the examination of the mode bits even in the VREG
- * case to avoid breakage for bogus servers, but we make sure
- * that there are actually type bits set in the upper part of
- * fa_mode (and failing that, trust the va_type field).
- *
- * NFSv3 cleared the issue, and requires fa_mode to not
- * contain any type information (while also introduing sockets
- * and FIFOs for fa_type).
- */
- if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
- vtyp = IFTOVT(vmode);
- rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
- fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
-
- /*
- * Really ugly NFSv2 kludge.
- */
- if (vtyp == VCHR && rdev == 0xffffffff)
- vtyp = VFIFO;
- }
-
- /*
- * If v_type == VNON it is a new node, so fill in the v_type,
- * n_mtime fields. Check to see if it represents a special
- * device, and if so, check for a possible alias. Once the
- * correct vnode has been obtained, fill in the rest of the
- * information.
- */
- np = VTONFS(vp);
- mtx_lock(&np->n_mtx);
- if (vp->v_type != vtyp) {
- vp->v_type = vtyp;
- if (vp->v_type == VFIFO)
- vp->v_op = &nfs_fifoops;
- np->n_mtime = mtime;
- }
- vap = &np->n_vattr;
- vap->va_type = vtyp;
- vap->va_mode = (vmode & 07777);
- vap->va_rdev = rdev;
- mtime_save = vap->va_mtime;
- vap->va_mtime = mtime;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- if (v3) {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_hyper(&fp->fa3_size);
- vap->va_blocksize = NFS_FABLKSIZE;
- vap->va_bytes = fxdr_hyper(&fp->fa3_used);
- vap->va_fileid = fxdr_unsigned(int32_t,
- fp->fa3_fileid.nfsuquad[1]);
- fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
- fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
- vap->va_flags = 0;
- vap->va_filerev = 0;
- } else {
- vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
- vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
- vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
- vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
- vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize);
- vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks)
- * NFS_FABLKSIZE;
- vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
- fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
- vap->va_flags = 0;
- vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
- fp->fa2_ctime.nfsv2_sec);
- vap->va_ctime.tv_nsec = 0;
- vap->va_gen = fxdr_unsigned(u_int32_t, fp->fa2_ctime.nfsv2_usec);
- vap->va_filerev = 0;
- }
- np->n_attrstamp = time_second;
- setnsize = 0;
- nsize = 0;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (dontshrink && vap->va_size < np->n_size) {
- /*
- * We've been told not to shrink the file;
- * zero np->n_attrstamp to indicate that
- * the attributes are stale.
- */
- vap->va_size = np->n_size;
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- vnode_pager_setsize(vp, np->n_size);
- } else if (np->n_flag & NMODIFIED) {
- /*
- * We've modified the file: Use the larger
- * of our size, and the server's size.
- */
- if (vap->va_size < np->n_size) {
- vap->va_size = np->n_size;
- } else {
- np->n_size = vap->va_size;
- np->n_flag |= NSIZECHANGED;
- }
- vnode_pager_setsize(vp, np->n_size);
- } else if (vap->va_size < np->n_size) {
- /*
- * When shrinking the size, the call to
- * vnode_pager_setsize() cannot be done
- * with the mutex held, so delay it until
- * after the mtx_unlock call.
- */
- nsize = np->n_size = vap->va_size;
- np->n_flag |= NSIZECHANGED;
- setnsize = 1;
- } else {
- np->n_size = vap->va_size;
- np->n_flag |= NSIZECHANGED;
- vnode_pager_setsize(vp, np->n_size);
- }
- } else {
- np->n_size = vap->va_size;
- }
- }
- /*
- * The following checks are added to prevent a race between (say)
- * a READDIR+ and a WRITE.
- * READDIR+, WRITE requests sent out.
- * READDIR+ resp, WRITE resp received on client.
- * However, the WRITE resp was handled before the READDIR+ resp
- * causing the post op attrs from the write to be loaded first
- * and the attrs from the READDIR+ to be loaded later. If this
- * happens, we have stale attrs loaded into the attrcache.
- * We detect this by for the mtime moving back. We invalidate the
- * attrcache when this happens.
- */
- if (timespeccmp(&mtime_save, &vap->va_mtime, >)) {
- /* Size changed or mtime went backwards */
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- }
- if (vaper != NULL) {
- bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
- if (np->n_flag & NCHG) {
- if (np->n_flag & NACC)
- vaper->va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vaper->va_mtime = np->n_mtim;
- }
- }
-
-#ifdef KDTRACE_HOOKS
- if (np->n_attrstamp != 0)
- KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, &np->n_vattr, 0);
-#endif
- mtx_unlock(&np->n_mtx);
- if (setnsize)
- vnode_pager_setsize(vp, nsize);
-out:
-#ifdef KDTRACE_HOOKS
- if (error)
- KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, NULL, error);
-#endif
- return (error);
-}
-
-#ifdef NFS_ACDEBUG
-#include <sys/sysctl.h>
-SYSCTL_DECL(_vfs_oldnfs);
-static int nfs_acdebug;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0,
- "Toggle acdebug (attribute cache debug) flag");
-#endif
-
-/*
- * Check the time stamp
- * If the cache is valid, copy contents to *vap and return 0
- * otherwise return an error
- */
-int
-nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
-{
- struct nfsnode *np;
- struct vattr *vap;
- struct nfsmount *nmp;
- int timeo;
-
- np = VTONFS(vp);
- vap = &np->n_vattr;
- nmp = VFSTONFS(vp->v_mount);
-#ifdef NFS_ACDEBUG
- mtx_lock(&Giant); /* nfs_printf() */
-#endif
- mtx_lock(&np->n_mtx);
- /* XXX n_mtime doesn't seem to be updated on a miss-and-reload */
- timeo = (time_second - np->n_mtime.tv_sec) / 10;
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug>1)
- nfs_printf("nfs_getattrcache: initial timeo = %d\n", timeo);
-#endif
-
- if (vap->va_type == VDIR) {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acdirmin)
- timeo = nmp->nm_acdirmin;
- else if (timeo > nmp->nm_acdirmax)
- timeo = nmp->nm_acdirmax;
- } else {
- if ((np->n_flag & NMODIFIED) || timeo < nmp->nm_acregmin)
- timeo = nmp->nm_acregmin;
- else if (timeo > nmp->nm_acregmax)
- timeo = nmp->nm_acregmax;
- }
-
-#ifdef NFS_ACDEBUG
- if (nfs_acdebug > 2)
- nfs_printf("acregmin %d; acregmax %d; acdirmin %d; acdirmax %d\n",
- nmp->nm_acregmin, nmp->nm_acregmax,
- nmp->nm_acdirmin, nmp->nm_acdirmax);
-
- if (nfs_acdebug)
- nfs_printf("nfs_getattrcache: age = %d; final timeo = %d\n",
- (time_second - np->n_attrstamp), timeo);
-#endif
-
- if ((time_second - np->n_attrstamp) >= timeo) {
- nfsstats.attrcache_misses++;
- mtx_unlock(&np->n_mtx);
-#ifdef NFS_ACDEBUG
- mtx_unlock(&Giant); /* nfs_printf() */
-#endif
- KDTRACE_NFS_ATTRCACHE_GET_MISS(vp);
- return (ENOENT);
- }
- nfsstats.attrcache_hits++;
- if (vap->va_size != np->n_size) {
- if (vap->va_type == VREG) {
- if (np->n_flag & NMODIFIED) {
- if (vap->va_size < np->n_size)
- vap->va_size = np->n_size;
- else
- np->n_size = vap->va_size;
- } else {
- np->n_size = vap->va_size;
- }
- vnode_pager_setsize(vp, np->n_size);
- } else {
- np->n_size = vap->va_size;
- }
- }
- bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
- if (np->n_flag & NCHG) {
- if (np->n_flag & NACC)
- vaper->va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vaper->va_mtime = np->n_mtim;
- }
- mtx_unlock(&np->n_mtx);
-#ifdef NFS_ACDEBUG
- mtx_unlock(&Giant); /* nfs_printf() */
-#endif
- KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
- return (0);
-}
-
-/*
- * Purge all cached information about an NFS vnode including name
- * cache entries, the attribute cache, and the access cache. This is
- * called when an NFS request for a node fails with a stale
- * filehandle.
- */
-void
-nfs_purgecache(struct vnode *vp)
-{
- struct nfsnode *np;
- int i;
-
- np = VTONFS(vp);
- cache_purge(vp);
- mtx_lock(&np->n_mtx);
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
- np->n_accesscache[i].stamp = 0;
- KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
- mtx_unlock(&np->n_mtx);
-}
-
-static nfsuint64 nfs_nullcookie = { { 0, 0 } };
-/*
- * This function finds the directory cookie that corresponds to the
- * logical byte offset given.
- */
-nfsuint64 *
-nfs_getcookie(struct nfsnode *np, off_t off, int add)
-{
- struct nfsdmap *dp, *dp2;
- int pos;
- nfsuint64 *retval = NULL;
-
- pos = (uoff_t)off / NFS_DIRBLKSIZ;
- if (pos == 0 || off < 0) {
- KASSERT(!add, ("nfs getcookie add at <= 0"));
- return (&nfs_nullcookie);
- }
- pos--;
- dp = LIST_FIRST(&np->n_cookies);
- if (!dp) {
- if (add) {
- dp = malloc(sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp->ndm_eocookie = 0;
- LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
- } else
- goto out;
- }
- while (pos >= NFSNUMCOOKIES) {
- pos -= NFSNUMCOOKIES;
- if (LIST_NEXT(dp, ndm_list)) {
- if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
- pos >= dp->ndm_eocookie)
- goto out;
- dp = LIST_NEXT(dp, ndm_list);
- } else if (add) {
- dp2 = malloc(sizeof (struct nfsdmap),
- M_NFSDIROFF, M_WAITOK);
- dp2->ndm_eocookie = 0;
- LIST_INSERT_AFTER(dp, dp2, ndm_list);
- dp = dp2;
- } else
- goto out;
- }
- if (pos >= dp->ndm_eocookie) {
- if (add)
- dp->ndm_eocookie = pos + 1;
- else
- goto out;
- }
- retval = &dp->ndm_cookies[pos];
-out:
- return (retval);
-}
-
-/*
- * Invalidate cached directory information, except for the actual directory
- * blocks (which are invalidated separately).
- * Done mainly to avoid the use of stale offset cookies.
- */
-void
-nfs_invaldir(struct vnode *vp)
-{
- struct nfsnode *np = VTONFS(vp);
-
- KASSERT(vp->v_type == VDIR, ("nfs: invaldir not dir"));
- nfs_dircookie_lock(np);
- np->n_direofoffset = 0;
- np->n_cookieverf.nfsuquad[0] = 0;
- np->n_cookieverf.nfsuquad[1] = 0;
- if (LIST_FIRST(&np->n_cookies))
- LIST_FIRST(&np->n_cookies)->ndm_eocookie = 0;
- nfs_dircookie_unlock(np);
-}
-
-/*
- * The write verifier has changed (probably due to a server reboot), so all
- * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
- * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
- * and B_CLUSTEROK flags. Once done the new write verifier can be set for the
- * mount point.
- *
- * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data
- * writes are not clusterable.
- */
-void
-nfs_clearcommit(struct mount *mp)
-{
- struct vnode *vp, *nvp;
- struct buf *bp, *nbp;
- struct bufobj *bo;
-
- MNT_VNODE_FOREACH_ALL(vp, mp, nvp) {
- bo = &vp->v_bufobj;
- vholdl(vp);
- VI_UNLOCK(vp);
- BO_LOCK(bo);
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (!BUF_ISLOCKED(bp) &&
- (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- }
- BO_UNLOCK(bo);
- vdrop(vp);
- }
-}
-
-/*
- * Helper functions for former macros. Some of these should be
- * moved to their callers.
- */
-
-int
-nfsm_mtofh_xx(struct vnode *d, struct vnode **v, int v3, int *f,
- struct mbuf **md, caddr_t *dpos)
-{
- struct nfsnode *ttnp;
- struct vnode *ttvp;
- nfsfh_t *ttfhp;
- u_int32_t *tl;
- int ttfhsize;
- int t1;
-
- if (v3) {
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *f = fxdr_unsigned(int, *tl);
- } else
- *f = 1;
- if (*f) {
- t1 = nfsm_getfh_xx(&ttfhp, &ttfhsize, (v3), md, dpos);
- if (t1 != 0)
- return t1;
- t1 = nfs_nget(d->v_mount, ttfhp, ttfhsize, &ttnp, LK_EXCLUSIVE);
- if (t1 != 0)
- return t1;
- *v = NFSTOV(ttnp);
- }
- if (v3) {
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*f)
- *f = fxdr_unsigned(int, *tl);
- else if (fxdr_unsigned(int, *tl))
- nfsm_adv_xx(NFSX_V3FATTR, md, dpos);
- }
- if (*f) {
- ttvp = *v;
- t1 = nfs_loadattrcache(&ttvp, md, dpos, NULL, 0);
- if (t1)
- return t1;
- *v = ttvp;
- }
- return 0;
-}
-
-int
-nfsm_getfh_xx(nfsfh_t **f, int *s, int v3, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
-
- if (v3) {
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *s = fxdr_unsigned(int, *tl);
- if (*s <= 0 || *s > NFSX_V3FHMAX)
- return EBADRPC;
- } else
- *s = NFSX_V2FH;
- *f = nfsm_dissect_xx(nfsm_rndup(*s), md, dpos);
- if (*f == NULL)
- return EBADRPC;
- else
- return 0;
-}
-
-
-int
-nfsm_loadattr_xx(struct vnode **v, struct vattr *va, struct mbuf **md,
- caddr_t *dpos)
-{
- int t1;
-
- struct vnode *ttvp = *v;
- t1 = nfs_loadattrcache(&ttvp, md, dpos, va, 0);
- if (t1 != 0)
- return t1;
- *v = ttvp;
- return 0;
-}
-
-int
-nfsm_postop_attr_xx(struct vnode **v, int *f, struct vattr *va,
- struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
- int t1;
-
- struct vnode *ttvp = *v;
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *f = fxdr_unsigned(int, *tl);
- if (*f != 0) {
- t1 = nfs_loadattrcache(&ttvp, md, dpos, va, 1);
- if (t1 != 0) {
- *f = 0;
- return t1;
- }
- *v = ttvp;
- }
- return 0;
-}
-
-int
-nfsm_wcc_data_xx(struct vnode **v, int *f, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
- int ttattrf, ttretf = 0;
- int t1;
-
- tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*tl == nfs_true) {
- tl = nfsm_dissect_xx(6 * NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- mtx_lock(&(VTONFS(*v))->n_mtx);
- if (*f)
- ttretf = (VTONFS(*v)->n_mtime.tv_sec == fxdr_unsigned(u_int32_t, *(tl + 2)) &&
- VTONFS(*v)->n_mtime.tv_nsec == fxdr_unsigned(u_int32_t, *(tl + 3)));
- mtx_unlock(&(VTONFS(*v))->n_mtx);
- }
- t1 = nfsm_postop_attr_xx(v, &ttattrf, NULL, md, dpos);
- if (t1)
- return t1;
- if (*f)
- *f = ttretf;
- else
- *f = ttattrf;
- return 0;
-}
-
-int
-nfsm_strtom_xx(const char *a, int s, int m, struct mbuf **mb, caddr_t *bpos)
-{
- u_int32_t *tl;
- int t1;
-
- if (s > m)
- return ENAMETOOLONG;
- t1 = nfsm_rndup(s) + NFSX_UNSIGNED;
- if (t1 <= M_TRAILINGSPACE(*mb)) {
- tl = nfsm_build_xx(t1, mb, bpos);
- *tl++ = txdr_unsigned(s);
- *(tl + ((t1 >> 2) - 2)) = 0;
- bcopy(a, tl, s);
- } else {
- t1 = nfsm_strtmbuf(mb, bpos, a, s);
- if (t1 != 0)
- return t1;
- }
- return 0;
-}
-
-int
-nfsm_fhtom_xx(struct vnode *v, int v3, struct mbuf **mb, caddr_t *bpos)
-{
- u_int32_t *tl;
- int t1;
- caddr_t cp;
-
- if (v3) {
- t1 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED;
- if (t1 < M_TRAILINGSPACE(*mb)) {
- tl = nfsm_build_xx(t1, mb, bpos);
- *tl++ = txdr_unsigned(VTONFS(v)->n_fhsize);
- *(tl + ((t1 >> 2) - 2)) = 0;
- bcopy(VTONFS(v)->n_fhp, tl, VTONFS(v)->n_fhsize);
- } else {
- t1 = nfsm_strtmbuf(mb, bpos,
- (const char *)VTONFS(v)->n_fhp,
- VTONFS(v)->n_fhsize);
- if (t1 != 0)
- return t1;
- }
- } else {
- cp = nfsm_build_xx(NFSX_V2FH, mb, bpos);
- bcopy(VTONFS(v)->n_fhp, cp, NFSX_V2FH);
- }
- return 0;
-}
-
-void
-nfsm_v3attrbuild_xx(struct vattr *va, int full, struct mbuf **mb,
- caddr_t *bpos)
-{
- u_int32_t *tl;
-
- if (va->va_mode != (mode_t)VNOVAL) {
- tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = nfs_true;
- *tl = txdr_unsigned(va->va_mode);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = nfs_false;
- }
- if (full && va->va_uid != (uid_t)VNOVAL) {
- tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = nfs_true;
- *tl = txdr_unsigned(va->va_uid);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = nfs_false;
- }
- if (full && va->va_gid != (gid_t)VNOVAL) {
- tl = nfsm_build_xx(2 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = nfs_true;
- *tl = txdr_unsigned(va->va_gid);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = nfs_false;
- }
- if (full && va->va_size != VNOVAL) {
- tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = nfs_true;
- txdr_hyper(va->va_size, tl);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = nfs_false;
- }
- if (va->va_atime.tv_sec != VNOVAL) {
- if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
- tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
- txdr_nfsv3time(&va->va_atime, tl);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
- }
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- }
- if (va->va_mtime.tv_sec != VNOVAL) {
- if ((va->va_vaflags & VA_UTIMES_NULL) == 0) {
- tl = nfsm_build_xx(3 * NFSX_UNSIGNED, mb, bpos);
- *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
- txdr_nfsv3time(&va->va_mtime, tl);
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
- }
- } else {
- tl = nfsm_build_xx(NFSX_UNSIGNED, mb, bpos);
- *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
- }
-}
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
deleted file mode 100644
index 0c002d2..0000000
--- a/sys/nfsclient/nfs_vfsops.c
+++ /dev/null
@@ -1,1582 +0,0 @@
-/*-
- * Copyright (c) 1989, 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.
- * 4. 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.
- *
- * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-
-#include "opt_bootp.h"
-#include "opt_nfsroot.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/jail.h>
-#include <sys/limits.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sockio.h>
-#include <sys/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/vnode.h>
-#include <sys/signalvar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/uma.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/route.h>
-#include <net/vnet.h>
-
-#include <netinet/in.h>
-
-#include <rpc/rpc.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsnode.h>
-#include <nfsclient/nfsmount.h>
-#include <nfs/xdr_subs.h>
-#include <nfsclient/nfsm_subs.h>
-#include <nfs/nfsdiskless.h>
-
-FEATURE(nfsclient, "NFS client");
-
-MALLOC_DEFINE(M_NFSREQ, "nfsclient_req", "NFS request header");
-MALLOC_DEFINE(M_NFSBIGFH, "nfsclient_bigfh", "NFS version 3 file handle");
-MALLOC_DEFINE(M_NFSDIROFF, "nfsclient_diroff", "NFS directory offset data");
-MALLOC_DEFINE(M_NFSHASH, "nfsclient_hash", "NFS hash tables");
-MALLOC_DEFINE(M_NFSDIRECTIO, "nfsclient_directio", "NFS Direct IO async write state");
-
-uma_zone_t nfsmount_zone;
-
-struct nfsstats nfsstats;
-
-SYSCTL_NODE(_vfs, OID_AUTO, oldnfs, CTLFLAG_RW, 0, "Old NFS filesystem");
-SYSCTL_STRUCT(_vfs_oldnfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RW,
- &nfsstats, nfsstats, "S,nfsstats");
-static int nfs_ip_paranoia = 1;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
- &nfs_ip_paranoia, 0,
- "Disallow accepting replies from IPs which differ from those sent");
-#ifdef NFS_DEBUG
-int nfs_debug;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
- "Toggle debug flag");
-#endif
-static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
-SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_INITIAL_DELAY,
- downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0,
- "Delay before printing \"nfs server not responding\" messages");
-/* how long between console messages "nfs server foo not responding" */
-static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
-SYSCTL_INT(_vfs_oldnfs, NFS_TPRINTF_DELAY,
- downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0,
- "Delay between printing \"nfs server not responding\" messages");
-
-static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
- struct nfs_args *argp, const char *hostname);
-static int mountnfs(struct nfs_args *, struct mount *,
- struct sockaddr *, char *, struct vnode **,
- struct ucred *cred, int, int);
-static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
- struct sockaddr_storage *, int *, off_t *,
- struct timeval *);
-static vfs_mount_t nfs_mount;
-static vfs_cmount_t nfs_cmount;
-static vfs_unmount_t nfs_unmount;
-static vfs_root_t nfs_root;
-static vfs_statfs_t nfs_statfs;
-static vfs_sync_t nfs_sync;
-static vfs_sysctl_t nfs_sysctl;
-
-static int fake_wchan;
-
-/*
- * nfs vfs operations.
- */
-static struct vfsops nfs_vfsops = {
- .vfs_init = nfs_init,
- .vfs_mount = nfs_mount,
- .vfs_cmount = nfs_cmount,
- .vfs_root = nfs_root,
- .vfs_statfs = nfs_statfs,
- .vfs_sync = nfs_sync,
- .vfs_uninit = nfs_uninit,
- .vfs_unmount = nfs_unmount,
- .vfs_sysctl = nfs_sysctl,
-};
-VFS_SET(nfs_vfsops, oldnfs, VFCF_NETWORK | VFCF_SBDRY);
-
-/* So that loader and kldload(2) can find us, wherever we are.. */
-MODULE_VERSION(oldnfs, 1);
-MODULE_DEPEND(oldnfs, krpc, 1, 1, 1);
-#ifdef KGSSAPI
-MODULE_DEPEND(oldnfs, kgssapi, 1, 1, 1);
-#endif
-MODULE_DEPEND(oldnfs, nfs_common, 1, 1, 1);
-MODULE_DEPEND(oldnfs, nfslock, 1, 1, 1);
-
-static struct nfs_rpcops nfs_rpcops = {
- nfs_readrpc,
- nfs_writerpc,
- nfs_writebp,
- nfs_readlinkrpc,
- nfs_invaldir,
- nfs_commit,
-};
-
-/*
- * This structure is now defined in sys/nfs/nfs_diskless.c so that it
- * can be shared by both NFS clients. It is declared here so that it
- * will be defined for kernels built without NFS_ROOT, although it
- * isn't used in that case.
- */
-#ifndef NFS_ROOT
-struct nfs_diskless nfs_diskless = { { { 0 } } };
-struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
-int nfs_diskless_valid = 0;
-#endif
-
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
- &nfs_diskless_valid, 0,
- "Has the diskless struct been filled correctly");
-
-SYSCTL_STRING(_vfs_oldnfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
- nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
-
-SYSCTL_OPAQUE(_vfs_oldnfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
- &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
- "%Ssockaddr_in", "Diskless root nfs address");
-
-
-void nfsargs_ntoh(struct nfs_args *);
-static int nfs_mountdiskless(char *,
- struct sockaddr_in *, struct nfs_args *,
- struct thread *, struct vnode **, struct mount *);
-static void nfs_convert_diskless(void);
-static void nfs_convert_oargs(struct nfs_args *args,
- struct onfs_args *oargs);
-
-int
-nfs_iosize(struct nfsmount *nmp)
-{
- int iosize;
-
- /*
- * Calculate the size used for io buffers. Use the larger
- * of the two sizes to minimise nfs requests but make sure
- * that it is at least one VM page to avoid wasting buffer
- * space.
- */
- iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
- iosize = imax(iosize, PAGE_SIZE);
- return (iosize);
-}
-
-static void
-nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
-{
-
- args->version = NFS_ARGSVERSION;
- args->addr = oargs->addr;
- args->addrlen = oargs->addrlen;
- args->sotype = oargs->sotype;
- args->proto = oargs->proto;
- args->fh = oargs->fh;
- args->fhsize = oargs->fhsize;
- args->flags = oargs->flags;
- args->wsize = oargs->wsize;
- args->rsize = oargs->rsize;
- args->readdirsize = oargs->readdirsize;
- args->timeo = oargs->timeo;
- args->retrans = oargs->retrans;
- args->maxgrouplist = oargs->maxgrouplist;
- args->readahead = oargs->readahead;
- args->deadthresh = oargs->deadthresh;
- args->hostname = oargs->hostname;
-}
-
-static void
-nfs_convert_diskless(void)
-{
-
- bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
- sizeof(struct ifaliasreq));
- bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
- sizeof(struct sockaddr_in));
- nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
- if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
- nfsv3_diskless.root_fhsize = NFSX_V3FH;
- bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V3FH);
- } else {
- nfsv3_diskless.root_fhsize = NFSX_V2FH;
- bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
- }
- bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
- sizeof(struct sockaddr_in));
- bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
- nfsv3_diskless.root_time = nfs_diskless.root_time;
- bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
- MAXHOSTNAMELEN);
- nfs_diskless_valid = 3;
-}
-
-/*
- * nfs statfs call
- */
-static int
-nfs_statfs(struct mount *mp, struct statfs *sbp)
-{
- struct vnode *vp;
- struct thread *td;
- struct nfs_statfs *sfp;
- caddr_t bpos, dpos;
- struct nfsmount *nmp = VFSTONFS(mp);
- int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct nfsnode *np;
- u_quad_t tquad;
-
- td = curthread;
-#ifndef nolint
- sfp = NULL;
-#endif
- error = vfs_busy(mp, MBF_NOWAIT);
- if (error)
- return (error);
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
- if (error) {
- vfs_unbusy(mp);
- return (error);
- }
- vp = NFSTOV(np);
- mtx_lock(&nmp->nm_mtx);
- if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
- } else
- mtx_unlock(&nmp->nm_mtx);
- nfsstats.rpccnt[NFSPROC_FSSTAT]++;
- mreq = m_get2(NFSX_FH(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
- if (v3)
- nfsm_postop_attr(vp, retattr);
- if (error) {
- if (mrep != NULL)
- m_freem(mrep);
- goto nfsmout;
- }
- sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
- mtx_lock(&nmp->nm_mtx);
- sbp->f_iosize = nfs_iosize(nmp);
- mtx_unlock(&nmp->nm_mtx);
- if (v3) {
- sbp->f_bsize = NFS_FABLKSIZE;
- tquad = fxdr_hyper(&sfp->sf_tbytes);
- sbp->f_blocks = tquad / NFS_FABLKSIZE;
- tquad = fxdr_hyper(&sfp->sf_fbytes);
- sbp->f_bfree = tquad / NFS_FABLKSIZE;
- tquad = fxdr_hyper(&sfp->sf_abytes);
- sbp->f_bavail = tquad / NFS_FABLKSIZE;
- sbp->f_files = (fxdr_unsigned(int32_t,
- sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
- sbp->f_ffree = (fxdr_unsigned(int32_t,
- sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
- } else {
- sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
- sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
- sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
- sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
- sbp->f_files = 0;
- sbp->f_ffree = 0;
- }
- m_freem(mrep);
-nfsmout:
- vput(vp);
- vfs_unbusy(mp);
- return (error);
-}
-
-/*
- * nfs version 3 fsinfo rpc call
- */
-int
-nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
- struct thread *td)
-{
- struct nfsv3_fsinfo *fsp;
- u_int32_t pref, max;
- caddr_t bpos, dpos;
- int error = 0, retattr;
- struct mbuf *mreq, *mrep, *md, *mb;
- u_int64_t maxfsize;
-
- nfsstats.rpccnt[NFSPROC_FSINFO]++;
- mreq = m_get2(NFSX_FH(1), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, 1);
- nfsm_request(vp, NFSPROC_FSINFO, td, cred);
- nfsm_postop_attr(vp, retattr);
- if (!error) {
- fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
- pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
- mtx_lock(&nmp->nm_mtx);
- if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
- nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
- ~(NFS_FABLKSIZE - 1);
- max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
- if (max < nmp->nm_wsize && max > 0) {
- nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_wsize == 0)
- nmp->nm_wsize = max;
- }
- pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
- if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
- nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
- ~(NFS_FABLKSIZE - 1);
- max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
- if (max < nmp->nm_rsize && max > 0) {
- nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_rsize == 0)
- nmp->nm_rsize = max;
- }
- pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
- if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
- nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
- ~(NFS_DIRBLKSIZ - 1);
- if (max < nmp->nm_readdirsize && max > 0) {
- nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
- if (nmp->nm_readdirsize == 0)
- nmp->nm_readdirsize = max;
- }
- maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
- if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
- nmp->nm_maxfilesize = maxfsize;
- nmp->nm_mountp->mnt_stat.f_iosize = nfs_iosize(nmp);
- nmp->nm_state |= NFSSTA_GOTFSINFO;
- mtx_unlock(&nmp->nm_mtx);
- }
- m_freem(mrep);
-nfsmout:
- return (error);
-}
-
-/*
- * Mount a remote root fs via. nfs. This depends on the info in the
- * nfs_diskless structure that has been filled in properly by some primary
- * bootstrap.
- * It goes something like this:
- * - do enough of "ifconfig" by calling ifioctl() so that the system
- * can talk to the server
- * - If nfs_diskless.mygateway is filled in, use that address as
- * a default gateway.
- * - build the rootfs mount point and call mountnfs() to do the rest.
- *
- * It is assumed to be safe to read, modify, and write the nfsv3_diskless
- * structure, as well as other global NFS client variables here, as
- * nfs_mountroot() will be called once in the boot before any other NFS
- * client activity occurs.
- */
-int
-nfs_mountroot(struct mount *mp)
-{
- struct thread *td = curthread;
- struct nfsv3_diskless *nd = &nfsv3_diskless;
- struct socket *so;
- struct vnode *vp;
- struct ifreq ir;
- int error;
- u_long l;
- char buf[128];
- char *cp;
-
-
-#if defined(BOOTP_NFSROOT) && defined(BOOTP)
- bootpc_init(); /* use bootp to get nfs_diskless filled in */
-#elif defined(NFS_ROOT)
- nfs_setup_diskless();
-#endif
-
- if (nfs_diskless_valid == 0) {
- return (-1);
- }
- if (nfs_diskless_valid == 1)
- nfs_convert_diskless();
-
- /*
- * XXX splnet, so networks will receive...
- */
- splnet();
-
- /*
- * Do enough of ifconfig(8) so that the critical net interface can
- * talk to the server.
- */
- error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
- td->td_ucred, td);
- if (error)
- panic("nfs_mountroot: socreate(%04x): %d",
- nd->myif.ifra_addr.sa_family, error);
-
-#if 0 /* XXX Bad idea */
- /*
- * We might not have been told the right interface, so we pass
- * over the first ten interfaces of the same kind, until we get
- * one of them configured.
- */
-
- for (i = strlen(nd->myif.ifra_name) - 1;
- nd->myif.ifra_name[i] >= '0' &&
- nd->myif.ifra_name[i] <= '9';
- nd->myif.ifra_name[i] ++) {
- error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
- if(!error)
- break;
- }
-#endif
-
- error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
- if (error)
- panic("nfs_mountroot: SIOCAIFADDR: %d", error);
-
- if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
- ir.ifr_mtu = strtol(cp, NULL, 10);
- bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
- freeenv(cp);
- error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
- if (error)
- printf("nfs_mountroot: SIOCSIFMTU: %d", error);
- }
- soclose(so);
-
- /*
- * If the gateway field is filled in, set it as the default route.
- * Note that pxeboot will set a default route of 0 if the route
- * is not set by the DHCP server. Check also for a value of 0
- * to avoid panicking inappropriately in that situation.
- */
- if (nd->mygateway.sin_len != 0 &&
- nd->mygateway.sin_addr.s_addr != 0) {
- struct sockaddr_in mask, sin;
-
- bzero((caddr_t)&mask, sizeof(mask));
- sin = mask;
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- /* XXX MRT use table 0 for this sort of thing */
- CURVNET_SET(TD_TO_VNET(td));
- error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
- (struct sockaddr *)&nd->mygateway,
- (struct sockaddr *)&mask,
- RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
- CURVNET_RESTORE();
- if (error)
- panic("nfs_mountroot: RTM_ADD: %d", error);
- }
-
- /*
- * Create the rootfs mount point.
- */
- nd->root_args.fh = nd->root_fh;
- nd->root_args.fhsize = nd->root_fhsize;
- l = ntohl(nd->root_saddr.sin_addr.s_addr);
- snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
- (l >> 24) & 0xff, (l >> 16) & 0xff,
- (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
- printf("NFS ROOT: %s\n", buf);
- nd->root_args.hostname = buf;
- if ((error = nfs_mountdiskless(buf,
- &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
- return (error);
- }
-
- /*
- * This is not really an nfs issue, but it is much easier to
- * set hostname here and then let the "/etc/rc.xxx" files
- * mount the right /var based upon its preset value.
- */
- mtx_lock(&prison0.pr_mtx);
- strlcpy(prison0.pr_hostname, nd->my_hostnam,
- sizeof (prison0.pr_hostname));
- mtx_unlock(&prison0.pr_mtx);
- inittodr(ntohl(nd->root_time));
- return (0);
-}
-
-/*
- * Internal version of mount system call for diskless setup.
- */
-static int
-nfs_mountdiskless(char *path,
- struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
- struct vnode **vpp, struct mount *mp)
-{
- struct sockaddr *nam;
- int error;
-
- nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
- if ((error = mountnfs(args, mp, nam, path, vpp, td->td_ucred,
- NFS_DEFAULT_NAMETIMEO, NFS_DEFAULT_NEGNAMETIMEO)) != 0) {
- printf("nfs_mountroot: mount %s on /: %d\n", path, error);
- return (error);
- }
- return (0);
-}
-
-static int
-nfs_sec_name_to_num(char *sec)
-{
- if (!strcmp(sec, "krb5"))
- return (RPCSEC_GSS_KRB5);
- if (!strcmp(sec, "krb5i"))
- return (RPCSEC_GSS_KRB5I);
- if (!strcmp(sec, "krb5p"))
- return (RPCSEC_GSS_KRB5P);
- if (!strcmp(sec, "sys"))
- return (AUTH_SYS);
- /*
- * Userland should validate the string but we will try and
- * cope with unexpected values.
- */
- return (AUTH_SYS);
-}
-
-static void
-nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
- const char *hostname)
-{
- int s;
- int adjsock;
- int maxio;
- char *p;
- char *secname;
- char *principal;
-
- s = splnet();
-
- /*
- * Set read-only flag if requested; otherwise, clear it if this is
- * an update. If this is not an update, then either the read-only
- * flag is already clear, or this is a root mount and it was set
- * intentionally at some previous point.
- */
- if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
- MNT_ILOCK(mp);
- mp->mnt_flag |= MNT_RDONLY;
- MNT_IUNLOCK(mp);
- } else if (mp->mnt_flag & MNT_UPDATE) {
- MNT_ILOCK(mp);
- mp->mnt_flag &= ~MNT_RDONLY;
- MNT_IUNLOCK(mp);
- }
-
- /*
- * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
- * no sense in that context. Also, set up appropriate retransmit
- * and soft timeout behavior.
- */
- if (argp->sotype == SOCK_STREAM) {
- nmp->nm_flag &= ~NFSMNT_NOCONN;
- nmp->nm_flag |= NFSMNT_DUMBTIMR;
- nmp->nm_timeo = NFS_MAXTIMEO;
- nmp->nm_retry = NFS_RETRANS_TCP;
- }
-
- /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
- if ((argp->flags & NFSMNT_NFSV3) == 0)
- nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
-
- /* Re-bind if rsrvd port requested and wasn't on one */
- adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
- && (argp->flags & NFSMNT_RESVPORT);
- /* Also re-bind if we're switching to/from a connected UDP socket */
- adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
- (argp->flags & NFSMNT_NOCONN));
-
- /* Update flags atomically. Don't change the lock bits. */
- nmp->nm_flag = argp->flags | nmp->nm_flag;
- splx(s);
-
- if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
- nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
- if (nmp->nm_timeo < NFS_MINTIMEO)
- nmp->nm_timeo = NFS_MINTIMEO;
- else if (nmp->nm_timeo > NFS_MAXTIMEO)
- nmp->nm_timeo = NFS_MAXTIMEO;
- }
-
- if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
- nmp->nm_retry = argp->retrans;
- if (nmp->nm_retry > NFS_MAXREXMIT)
- nmp->nm_retry = NFS_MAXREXMIT;
- }
-
- if (argp->flags & NFSMNT_NFSV3) {
- if (argp->sotype == SOCK_DGRAM)
- maxio = NFS_MAXDGRAMDATA;
- else
- maxio = NFS_MAXDATA;
- } else
- maxio = NFS_V2MAXDATA;
-
- if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
- nmp->nm_wsize = argp->wsize;
- /* Round down to multiple of blocksize */
- nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_wsize <= 0)
- nmp->nm_wsize = NFS_FABLKSIZE;
- }
- if (nmp->nm_wsize > maxio)
- nmp->nm_wsize = maxio;
- if (nmp->nm_wsize > MAXBSIZE)
- nmp->nm_wsize = MAXBSIZE;
-
- if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
- nmp->nm_rsize = argp->rsize;
- /* Round down to multiple of blocksize */
- nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
- if (nmp->nm_rsize <= 0)
- nmp->nm_rsize = NFS_FABLKSIZE;
- }
- if (nmp->nm_rsize > maxio)
- nmp->nm_rsize = maxio;
- if (nmp->nm_rsize > MAXBSIZE)
- nmp->nm_rsize = MAXBSIZE;
-
- if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
- nmp->nm_readdirsize = argp->readdirsize;
- }
- if (nmp->nm_readdirsize > maxio)
- nmp->nm_readdirsize = maxio;
- if (nmp->nm_readdirsize > nmp->nm_rsize)
- nmp->nm_readdirsize = nmp->nm_rsize;
-
- if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
- nmp->nm_acregmin = argp->acregmin;
- else
- nmp->nm_acregmin = NFS_MINATTRTIMO;
- if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
- nmp->nm_acregmax = argp->acregmax;
- else
- nmp->nm_acregmax = NFS_MAXATTRTIMO;
- if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
- nmp->nm_acdirmin = argp->acdirmin;
- else
- nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
- if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
- nmp->nm_acdirmax = argp->acdirmax;
- else
- nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
- if (nmp->nm_acdirmin > nmp->nm_acdirmax)
- nmp->nm_acdirmin = nmp->nm_acdirmax;
- if (nmp->nm_acregmin > nmp->nm_acregmax)
- nmp->nm_acregmin = nmp->nm_acregmax;
-
- if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
- if (argp->maxgrouplist <= NFS_MAXGRPS)
- nmp->nm_numgrps = argp->maxgrouplist;
- else
- nmp->nm_numgrps = NFS_MAXGRPS;
- }
- if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
- if (argp->readahead <= NFS_MAXRAHEAD)
- nmp->nm_readahead = argp->readahead;
- else
- nmp->nm_readahead = NFS_MAXRAHEAD;
- }
- if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
- if (argp->wcommitsize < nmp->nm_wsize)
- nmp->nm_wcommitsize = nmp->nm_wsize;
- else
- nmp->nm_wcommitsize = argp->wcommitsize;
- }
- if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
- if (argp->deadthresh <= NFS_MAXDEADTHRESH)
- nmp->nm_deadthresh = argp->deadthresh;
- else
- nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
- }
-
- adjsock |= ((nmp->nm_sotype != argp->sotype) ||
- (nmp->nm_soproto != argp->proto));
- nmp->nm_sotype = argp->sotype;
- nmp->nm_soproto = argp->proto;
-
- if (nmp->nm_client && adjsock) {
- nfs_safedisconnect(nmp);
- if (nmp->nm_sotype == SOCK_DGRAM)
- while (nfs_connect(nmp)) {
- printf("nfs_args: retrying connect\n");
- (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
- }
- }
-
- if (hostname) {
- strlcpy(nmp->nm_hostname, hostname,
- sizeof(nmp->nm_hostname));
- p = strchr(nmp->nm_hostname, ':');
- if (p)
- *p = '\0';
- }
-
- if (vfs_getopt(mp->mnt_optnew, "sec",
- (void **) &secname, NULL) == 0) {
- nmp->nm_secflavor = nfs_sec_name_to_num(secname);
- } else {
- nmp->nm_secflavor = AUTH_SYS;
- }
-
- if (vfs_getopt(mp->mnt_optnew, "principal",
- (void **) &principal, NULL) == 0) {
- strlcpy(nmp->nm_principal, principal,
- sizeof(nmp->nm_principal));
- } else {
- snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
- "nfs@%s", nmp->nm_hostname);
- }
-}
-
-static const char *nfs_opts[] = { "from", "nfs_args",
- "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
- "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
- "async", "dumbtimer", "noconn", "nolockd", "intr", "rdirplus", "resvport",
- "readahead", "readdirsize", "soft", "hard", "mntudp", "tcp", "udp",
- "wsize", "rsize", "retrans", "acregmin", "acregmax", "acdirmin",
- "acdirmax", "deadthresh", "hostname", "timeout", "addr", "fh", "nfsv3",
- "sec", "maxgroups", "principal", "negnametimeo", "nocto", "wcommitsize",
- "nametimeo",
- NULL };
-
-/*
- * VFS Operations.
- *
- * mount system call
- * It seems a bit dumb to copyinstr() the host and path here and then
- * bcopy() them in mountnfs(), but I wanted to detect errors before
- * doing the sockargs() call because sockargs() allocates an mbuf and
- * an error after that means that I have to release the mbuf.
- */
-/* ARGSUSED */
-static int
-nfs_mount(struct mount *mp)
-{
- struct nfs_args args = {
- .version = NFS_ARGSVERSION,
- .addr = NULL,
- .addrlen = sizeof (struct sockaddr_in),
- .sotype = SOCK_STREAM,
- .proto = 0,
- .fh = NULL,
- .fhsize = 0,
- .flags = NFSMNT_RESVPORT,
- .wsize = NFS_WSIZE,
- .rsize = NFS_RSIZE,
- .readdirsize = NFS_READDIRSIZE,
- .timeo = 10,
- .retrans = NFS_RETRANS,
- .maxgrouplist = NFS_MAXGRPS,
- .readahead = NFS_DEFRAHEAD,
- .wcommitsize = 0, /* was: NQ_DEFLEASE */
- .deadthresh = NFS_MAXDEADTHRESH, /* was: NQ_DEADTHRESH */
- .hostname = NULL,
- /* args version 4 */
- .acregmin = NFS_MINATTRTIMO,
- .acregmax = NFS_MAXATTRTIMO,
- .acdirmin = NFS_MINDIRATTRTIMO,
- .acdirmax = NFS_MAXDIRATTRTIMO,
- };
- int error, ret, has_nfs_args_opt;
- int has_addr_opt, has_fh_opt, has_hostname_opt;
- struct sockaddr *nam;
- struct vnode *vp;
- char hst[MNAMELEN];
- size_t len;
- u_char nfh[NFSX_V3FHMAX];
- char *opt;
- int nametimeo = NFS_DEFAULT_NAMETIMEO;
- int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
-
- has_nfs_args_opt = 0;
- has_addr_opt = 0;
- has_fh_opt = 0;
- has_hostname_opt = 0;
-
- if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
- error = EINVAL;
- goto out;
- }
-
- if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
- error = nfs_mountroot(mp);
- goto out;
- }
-
- /*
- * The old mount_nfs program passed the struct nfs_args
- * from userspace to kernel. The new mount_nfs program
- * passes string options via nmount() from userspace to kernel
- * and we populate the struct nfs_args in the kernel.
- */
- if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
- error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
- sizeof args);
- if (error)
- goto out;
-
- if (args.version != NFS_ARGSVERSION) {
- error = EPROGMISMATCH;
- goto out;
- }
- has_nfs_args_opt = 1;
- }
-
- if (vfs_getopt(mp->mnt_optnew, "dumbtimer", NULL, NULL) == 0)
- args.flags |= NFSMNT_DUMBTIMR;
- if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
- args.flags |= NFSMNT_NOCONN;
- if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
- args.flags |= NFSMNT_NOCONN;
- if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
- args.flags |= NFSMNT_NOLOCKD;
- if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
- args.flags &= ~NFSMNT_NOLOCKD;
- if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
- args.flags |= NFSMNT_INT;
- if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
- args.flags |= NFSMNT_RDIRPLUS;
- if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
- args.flags |= NFSMNT_RESVPORT;
- if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
- args.flags &= ~NFSMNT_RESVPORT;
- if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
- args.flags |= NFSMNT_SOFT;
- if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
- args.flags &= ~NFSMNT_SOFT;
- if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
- args.sotype = SOCK_DGRAM;
- if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
- args.sotype = SOCK_DGRAM;
- if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
- args.sotype = SOCK_STREAM;
- if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
- args.flags |= NFSMNT_NFSV3;
- if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
- args.flags |= NFSMNT_NOCTO;
- if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
- if (opt == NULL) {
- vfs_mount_error(mp, "illegal readdirsize");
- error = EINVAL;
- goto out;
- }
- ret = sscanf(opt, "%d", &args.readdirsize);
- if (ret != 1 || args.readdirsize <= 0) {
- vfs_mount_error(mp, "illegal readdirsize: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_READDIRSIZE;
- }
- if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
- if (opt == NULL) {
- vfs_mount_error(mp, "illegal readahead");
- error = EINVAL;
- goto out;
- }
- ret = sscanf(opt, "%d", &args.readahead);
- if (ret != 1 || args.readahead <= 0) {
- vfs_mount_error(mp, "illegal readahead: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_READAHEAD;
- }
- if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
- if (opt == NULL) {
- vfs_mount_error(mp, "illegal wsize");
- error = EINVAL;
- goto out;
- }
- ret = sscanf(opt, "%d", &args.wsize);
- if (ret != 1 || args.wsize <= 0) {
- vfs_mount_error(mp, "illegal wsize: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_WSIZE;
- }
- if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
- if (opt == NULL) {
- vfs_mount_error(mp, "illegal rsize");
- error = EINVAL;
- goto out;
- }
- ret = sscanf(opt, "%d", &args.rsize);
- if (ret != 1 || args.rsize <= 0) {
- vfs_mount_error(mp, "illegal wsize: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_RSIZE;
- }
- if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
- if (opt == NULL) {
- vfs_mount_error(mp, "illegal retrans");
- error = EINVAL;
- goto out;
- }
- ret = sscanf(opt, "%d", &args.retrans);
- if (ret != 1 || args.retrans <= 0) {
- vfs_mount_error(mp, "illegal retrans: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_RETRANS;
- }
- if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.acregmin);
- if (ret != 1 || args.acregmin < 0) {
- vfs_mount_error(mp, "illegal acregmin: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_ACREGMIN;
- }
- if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.acregmax);
- if (ret != 1 || args.acregmax < 0) {
- vfs_mount_error(mp, "illegal acregmax: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_ACREGMAX;
- }
- if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.acdirmin);
- if (ret != 1 || args.acdirmin < 0) {
- vfs_mount_error(mp, "illegal acdirmin: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_ACDIRMIN;
- }
- if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.acdirmax);
- if (ret != 1 || args.acdirmax < 0) {
- vfs_mount_error(mp, "illegal acdirmax: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_ACDIRMAX;
- }
- if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.wcommitsize);
- if (ret != 1 || args.wcommitsize < 0) {
- vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_WCOMMITSIZE;
- }
- if (vfs_getopt(mp->mnt_optnew, "deadthresh", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.deadthresh);
- if (ret != 1 || args.deadthresh <= 0) {
- vfs_mount_error(mp, "illegal deadthresh: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_DEADTHRESH;
- }
- if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.timeo);
- if (ret != 1 || args.timeo <= 0) {
- vfs_mount_error(mp, "illegal timeout: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_TIMEO;
- }
- if (vfs_getopt(mp->mnt_optnew, "maxgroups", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &args.maxgrouplist);
- if (ret != 1 || args.maxgrouplist <= 0) {
- vfs_mount_error(mp, "illegal maxgroups: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- args.flags |= NFSMNT_MAXGRPS;
- }
- if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
- ret = sscanf(opt, "%d", &nametimeo);
- if (ret != 1 || nametimeo < 0) {
- vfs_mount_error(mp, "illegal nametimeo: %s", opt);
- error = EINVAL;
- goto out;
- }
- }
- if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
- == 0) {
- ret = sscanf(opt, "%d", &negnametimeo);
- if (ret != 1 || negnametimeo < 0) {
- vfs_mount_error(mp, "illegal negnametimeo: %s",
- opt);
- error = EINVAL;
- goto out;
- }
- }
- if (vfs_getopt(mp->mnt_optnew, "addr", (void **)&args.addr,
- &args.addrlen) == 0) {
- has_addr_opt = 1;
- if (args.addrlen > SOCK_MAXADDRLEN) {
- error = ENAMETOOLONG;
- goto out;
- }
- nam = malloc(args.addrlen, M_SONAME,
- M_WAITOK);
- bcopy(args.addr, nam, args.addrlen);
- nam->sa_len = args.addrlen;
- }
- if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
- &args.fhsize) == 0) {
- has_fh_opt = 1;
- }
- if (vfs_getopt(mp->mnt_optnew, "hostname", (void **)&args.hostname,
- NULL) == 0) {
- has_hostname_opt = 1;
- }
- if (args.hostname == NULL) {
- vfs_mount_error(mp, "Invalid hostname");
- error = EINVAL;
- goto out;
- }
- if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
- vfs_mount_error(mp, "Bad file handle");
- error = EINVAL;
- goto out;
- }
-
- if (mp->mnt_flag & MNT_UPDATE) {
- struct nfsmount *nmp = VFSTONFS(mp);
-
- if (nmp == NULL) {
- error = EIO;
- goto out;
- }
-
- /*
- * If a change from TCP->UDP is done and there are thread(s)
- * that have I/O RPC(s) in progress with a tranfer size
- * greater than NFS_MAXDGRAMDATA, those thread(s) will be
- * hung, retrying the RPC(s) forever. Usually these threads
- * will be seen doing an uninterruptible sleep on wait channel
- * "newnfsreq" (truncated to "newnfsre" by procstat).
- */
- if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
- tprintf(curthread->td_proc, LOG_WARNING,
- "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
-
- /*
- * When doing an update, we can't change from or to
- * v3, switch lockd strategies or change cookie translation
- */
- args.flags = (args.flags &
- ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
- (nmp->nm_flag &
- (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
- nfs_decode_args(mp, nmp, &args, NULL);
- goto out;
- }
-
- /*
- * Make the nfs_ip_paranoia sysctl serve as the default connection
- * or no-connection mode for those protocols that support
- * no-connection mode (the flag will be cleared later for protocols
- * that do not support no-connection mode). This will allow a client
- * to receive replies from a different IP then the request was
- * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
- * not 0.
- */
- if (nfs_ip_paranoia == 0)
- args.flags |= NFSMNT_NOCONN;
-
- if (has_nfs_args_opt) {
- /*
- * In the 'nfs_args' case, the pointers in the args
- * structure are in userland - we copy them in here.
- */
- if (!has_fh_opt) {
- error = copyin((caddr_t)args.fh, (caddr_t)nfh,
- args.fhsize);
- if (error) {
- goto out;
- }
- args.fh = nfh;
- }
- if (!has_hostname_opt) {
- error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
- if (error) {
- goto out;
- }
- bzero(&hst[len], MNAMELEN - len);
- args.hostname = hst;
- }
- if (!has_addr_opt) {
- /* sockargs() call must be after above copyin() calls */
- error = getsockaddr(&nam, (caddr_t)args.addr,
- args.addrlen);
- if (error) {
- goto out;
- }
- }
- } else if (has_addr_opt == 0) {
- vfs_mount_error(mp, "No server address");
- error = EINVAL;
- goto out;
- }
- error = mountnfs(&args, mp, nam, args.hostname, &vp,
- curthread->td_ucred, nametimeo, negnametimeo);
-out:
- if (!error) {
- MNT_ILOCK(mp);
- mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED;
- MNT_IUNLOCK(mp);
- }
- return (error);
-}
-
-
-/*
- * VFS Operations.
- *
- * mount system call
- * It seems a bit dumb to copyinstr() the host and path here and then
- * bcopy() them in mountnfs(), but I wanted to detect errors before
- * doing the sockargs() call because sockargs() allocates an mbuf and
- * an error after that means that I have to release the mbuf.
- */
-/* ARGSUSED */
-static int
-nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
-{
- int error;
- struct nfs_args args;
-
- error = copyin(data, &args, sizeof (struct nfs_args));
- if (error)
- return error;
-
- ma = mount_arg(ma, "nfs_args", &args, sizeof args);
-
- error = kernel_mount(ma, flags);
- return (error);
-}
-
-/*
- * Common code for mount and mountroot
- */
-static int
-mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
- char *hst, struct vnode **vpp, struct ucred *cred, int nametimeo,
- int negnametimeo)
-{
- struct nfsmount *nmp;
- struct nfsnode *np;
- int error;
- struct vattr attrs;
-
- if (mp->mnt_flag & MNT_UPDATE) {
- nmp = VFSTONFS(mp);
- printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
- free(nam, M_SONAME);
- return (0);
- } else {
- nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
- bzero((caddr_t)nmp, sizeof (struct nfsmount));
- TAILQ_INIT(&nmp->nm_bufq);
- mp->mnt_data = nmp;
- nmp->nm_getinfo = nfs_getnlminfo;
- nmp->nm_vinvalbuf = nfs_vinvalbuf;
- }
- vfs_getnewfsid(mp);
- nmp->nm_mountp = mp;
- mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF);
-
- /*
- * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
- * high, depending on whether we end up with negative offsets in
- * the client or server somewhere. 2GB-1 may be safer.
- *
- * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
- * that we can handle until we find out otherwise.
- */
- if ((argp->flags & NFSMNT_NFSV3) == 0)
- nmp->nm_maxfilesize = 0xffffffffLL;
- else
- nmp->nm_maxfilesize = OFF_MAX;
-
- nmp->nm_timeo = NFS_TIMEO;
- nmp->nm_retry = NFS_RETRANS;
- if ((argp->flags & NFSMNT_NFSV3) && argp->sotype == SOCK_STREAM) {
- nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDATA;
- } else {
- nmp->nm_wsize = NFS_WSIZE;
- nmp->nm_rsize = NFS_RSIZE;
- }
- nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
- nmp->nm_readdirsize = NFS_READDIRSIZE;
- nmp->nm_numgrps = NFS_MAXGRPS;
- nmp->nm_readahead = NFS_DEFRAHEAD;
- nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
- nmp->nm_nametimeo = nametimeo;
- nmp->nm_negnametimeo = negnametimeo;
- nmp->nm_tprintf_delay = nfs_tprintf_delay;
- if (nmp->nm_tprintf_delay < 0)
- nmp->nm_tprintf_delay = 0;
- nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
- if (nmp->nm_tprintf_initial_delay < 0)
- nmp->nm_tprintf_initial_delay = 0;
- nmp->nm_fhsize = argp->fhsize;
- bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
- bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
- nmp->nm_nam = nam;
- /* Set up the sockets and per-host congestion */
- nmp->nm_sotype = argp->sotype;
- nmp->nm_soproto = argp->proto;
- nmp->nm_rpcops = &nfs_rpcops;
-
- nfs_decode_args(mp, nmp, argp, hst);
-
- /*
- * For Connection based sockets (TCP,...) defer the connect until
- * the first request, in case the server is not responding.
- */
- if (nmp->nm_sotype == SOCK_DGRAM &&
- (error = nfs_connect(nmp)))
- goto bad;
-
- /*
- * This is silly, but it has to be set so that vinifod() works.
- * We do not want to do an nfs_statfs() here since we can get
- * stuck on a dead server and we are holding a lock on the mount
- * point.
- */
- mtx_lock(&nmp->nm_mtx);
- mp->mnt_stat.f_iosize = nfs_iosize(nmp);
- mtx_unlock(&nmp->nm_mtx);
- /*
- * A reference count is needed on the nfsnode representing the
- * remote root. If this object is not persistent, then backward
- * traversals of the mount point (i.e. "..") will not work if
- * the nfsnode gets flushed out of the cache. Ufs does not have
- * this problem, because one can identify root inodes by their
- * number == ROOTINO (2).
- */
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
- if (error)
- goto bad;
- *vpp = NFSTOV(np);
-
- /*
- * Get file attributes and transfer parameters for the
- * mountpoint. This has the side effect of filling in
- * (*vpp)->v_type with the correct value.
- */
- if (argp->flags & NFSMNT_NFSV3)
- nfs_fsinfo(nmp, *vpp, curthread->td_ucred, curthread);
- else
- VOP_GETATTR(*vpp, &attrs, curthread->td_ucred);
-
- /*
- * Lose the lock but keep the ref.
- */
- VOP_UNLOCK(*vpp, 0);
-
- return (0);
-bad:
- nfs_disconnect(nmp);
- mtx_destroy(&nmp->nm_mtx);
- uma_zfree(nfsmount_zone, nmp);
- free(nam, M_SONAME);
- return (error);
-}
-
-/*
- * unmount system call
- */
-static int
-nfs_unmount(struct mount *mp, int mntflags)
-{
- struct nfsmount *nmp;
- int error, flags = 0, i;
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
- nmp = VFSTONFS(mp);
- /*
- * Goes something like this..
- * - Call vflush() to clear out vnodes for this filesystem
- * - Close the socket
- * - Free up the data structures
- */
- /* In the forced case, cancel any outstanding requests. */
- if (flags & FORCECLOSE) {
- error = nfs_nmcancelreqs(nmp);
- if (error)
- goto out;
- }
- /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
- error = vflush(mp, 1, flags, curthread);
- if (error)
- goto out;
-
- /*
- * We are now committed to the unmount.
- */
- /* Make sure no nfsiods are assigned to this mount. */
- mtx_lock(&nfs_iod_mtx);
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
- if (nfs_iodmount[i] == nmp) {
- nfs_iodwant[i] = NFSIOD_AVAILABLE;
- nfs_iodmount[i] = NULL;
- }
- mtx_unlock(&nfs_iod_mtx);
- nfs_disconnect(nmp);
- free(nmp->nm_nam, M_SONAME);
-
- mtx_destroy(&nmp->nm_mtx);
- uma_zfree(nfsmount_zone, nmp);
-out:
- return (error);
-}
-
-/*
- * Return root of a filesystem
- */
-static int
-nfs_root(struct mount *mp, int flags, struct vnode **vpp)
-{
- struct vnode *vp;
- struct nfsmount *nmp;
- struct nfsnode *np;
- int error;
-
- nmp = VFSTONFS(mp);
- error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, flags);
- if (error)
- return error;
- vp = NFSTOV(np);
- /*
- * Get transfer parameters and attributes for root vnode once.
- */
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0 &&
- (nmp->nm_flag & NFSMNT_NFSV3)) {
- mtx_unlock(&nmp->nm_mtx);
- nfs_fsinfo(nmp, vp, curthread->td_ucred, curthread);
- } else
- mtx_unlock(&nmp->nm_mtx);
- if (vp->v_type == VNON)
- vp->v_type = VDIR;
- vp->v_vflag |= VV_ROOT;
- *vpp = vp;
- return (0);
-}
-
-/*
- * Flush out the buffer cache
- */
-/* ARGSUSED */
-static int
-nfs_sync(struct mount *mp, int waitfor)
-{
- struct vnode *vp, *mvp;
- struct thread *td;
- int error, allerror = 0;
-
- td = curthread;
-
- MNT_ILOCK(mp);
- /*
- * If a forced dismount is in progress, return from here so that
- * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
- * calling VFS_UNMOUNT().
- */
- if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
- MNT_IUNLOCK(mp);
- return (EBADF);
- }
- MNT_IUNLOCK(mp);
-
- /*
- * Force stale buffer cache information to be flushed.
- */
-loop:
- MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
- /* XXX Racy bv_cnt check. */
- if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
- waitfor == MNT_LAZY) {
- VI_UNLOCK(vp);
- continue;
- }
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
- MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
- goto loop;
- }
- error = VOP_FSYNC(vp, waitfor, td);
- if (error)
- allerror = error;
- VOP_UNLOCK(vp, 0);
- vrele(vp);
- }
- return (allerror);
-}
-
-static int
-nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
-{
- struct nfsmount *nmp = VFSTONFS(mp);
- struct vfsquery vq;
- int error;
-
- bzero(&vq, sizeof(vq));
- switch (op) {
-#if 0
- case VFS_CTL_NOLOCKS:
- val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
- if (req->oldptr != NULL) {
- error = SYSCTL_OUT(req, &val, sizeof(val));
- if (error)
- return (error);
- }
- if (req->newptr != NULL) {
- error = SYSCTL_IN(req, &val, sizeof(val));
- if (error)
- return (error);
- if (val)
- nmp->nm_flag |= NFSMNT_NOLOCKS;
- else
- nmp->nm_flag &= ~NFSMNT_NOLOCKS;
- }
- break;
-#endif
- case VFS_CTL_QUERY:
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_state & NFSSTA_TIMEO)
- vq.vq_flags |= VQ_NOTRESP;
- mtx_unlock(&nmp->nm_mtx);
-#if 0
- if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
- (nmp->nm_state & NFSSTA_LOCKTIMEO))
- vq.vq_flags |= VQ_NOTRESPLOCK;
-#endif
- error = SYSCTL_OUT(req, &vq, sizeof(vq));
- break;
- case VFS_CTL_TIMEO:
- if (req->oldptr != NULL) {
- error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
- sizeof(nmp->nm_tprintf_initial_delay));
- if (error)
- return (error);
- }
- if (req->newptr != NULL) {
- error = vfs_suser(mp, req->td);
- if (error)
- return (error);
- error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
- sizeof(nmp->nm_tprintf_initial_delay));
- if (error)
- return (error);
- if (nmp->nm_tprintf_initial_delay < 0)
- nmp->nm_tprintf_initial_delay = 0;
- }
- break;
- default:
- return (ENOTSUP);
- }
- return (0);
-}
-
-/*
- * Extract the information needed by the nlm from the nfs vnode.
- */
-static void
-nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
- struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
- struct timeval *timeop)
-{
- struct nfsmount *nmp;
- struct nfsnode *np = VTONFS(vp);
-
- nmp = VFSTONFS(vp->v_mount);
- if (fhlenp != NULL)
- *fhlenp = (size_t)np->n_fhsize;
- if (fhp != NULL)
- bcopy(np->n_fhp, fhp, np->n_fhsize);
- if (sp != NULL)
- bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
- if (is_v3p != NULL)
- *is_v3p = NFS_ISV3(vp);
- if (sizep != NULL)
- *sizep = np->n_size;
- if (timeop != NULL) {
- timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
- timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
- }
-}
-
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
deleted file mode 100644
index 2516d7d..0000000
--- a/sys/nfsclient/nfs_vnops.c
+++ /dev/null
@@ -1,3544 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * vnode op calls for Sun NFS version 2 and 3
- */
-
-#include "opt_inet.h"
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/resourcevar.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/jail.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/namei.h>
-#include <sys/socket.h>
-#include <sys/vnode.h>
-#include <sys/dirent.h>
-#include <sys/fcntl.h>
-#include <sys/lockf.h>
-#include <sys/rwlock.h>
-#include <sys/stat.h>
-#include <sys/sysctl.h>
-#include <sys/signalvar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsnode.h>
-#include <nfsclient/nfsmount.h>
-#include <nfs/nfs_kdtrace.h>
-#include <nfs/nfs_lock.h>
-#include <nfs/xdr_subs.h>
-#include <nfsclient/nfsm_subs.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/vnet.h>
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-
-#include <machine/stdarg.h>
-
-#ifdef KDTRACE_HOOKS
-#include <sys/dtrace_bsd.h>
-
-dtrace_nfsclient_accesscache_flush_probe_func_t
- dtrace_nfsclient_accesscache_flush_done_probe;
-uint32_t nfsclient_accesscache_flush_done_id;
-
-dtrace_nfsclient_accesscache_get_probe_func_t
- dtrace_nfsclient_accesscache_get_hit_probe,
- dtrace_nfsclient_accesscache_get_miss_probe;
-uint32_t nfsclient_accesscache_get_hit_id;
-uint32_t nfsclient_accesscache_get_miss_id;
-
-dtrace_nfsclient_accesscache_load_probe_func_t
- dtrace_nfsclient_accesscache_load_done_probe;
-uint32_t nfsclient_accesscache_load_done_id;
-#endif /* !KDTRACE_HOOKS */
-
-/* Defs */
-#define TRUE 1
-#define FALSE 0
-
-/*
- * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
- * calls are not in getblk() and brelse() so that they would not be necessary
- * here.
- */
-#ifndef B_VMIO
-#define vfs_busy_pages(bp, f)
-#endif
-
-static vop_read_t nfsfifo_read;
-static vop_write_t nfsfifo_write;
-static vop_close_t nfsfifo_close;
-static int nfs_flush(struct vnode *, int, int);
-static int nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *);
-static vop_lookup_t nfs_lookup;
-static vop_create_t nfs_create;
-static vop_mknod_t nfs_mknod;
-static vop_open_t nfs_open;
-static vop_close_t nfs_close;
-static vop_access_t nfs_access;
-static vop_getattr_t nfs_getattr;
-static vop_setattr_t nfs_setattr;
-static vop_read_t nfs_read;
-static vop_fsync_t nfs_fsync;
-static vop_remove_t nfs_remove;
-static vop_link_t nfs_link;
-static vop_rename_t nfs_rename;
-static vop_mkdir_t nfs_mkdir;
-static vop_rmdir_t nfs_rmdir;
-static vop_symlink_t nfs_symlink;
-static vop_readdir_t nfs_readdir;
-static vop_strategy_t nfs_strategy;
-static int nfs_lookitup(struct vnode *, const char *, int,
- struct ucred *, struct thread *, struct nfsnode **);
-static int nfs_sillyrename(struct vnode *, struct vnode *,
- struct componentname *);
-static vop_access_t nfsspec_access;
-static vop_readlink_t nfs_readlink;
-static vop_print_t nfs_print;
-static vop_advlock_t nfs_advlock;
-static vop_advlockasync_t nfs_advlockasync;
-
-/*
- * Global vfs data structures for nfs
- */
-struct vop_vector nfs_vnodeops = {
- .vop_default = &default_vnodeops,
- .vop_access = nfs_access,
- .vop_advlock = nfs_advlock,
- .vop_advlockasync = nfs_advlockasync,
- .vop_close = nfs_close,
- .vop_create = nfs_create,
- .vop_fsync = nfs_fsync,
- .vop_getattr = nfs_getattr,
- .vop_getpages = nfs_getpages,
- .vop_putpages = nfs_putpages,
- .vop_inactive = nfs_inactive,
- .vop_link = nfs_link,
- .vop_lookup = nfs_lookup,
- .vop_mkdir = nfs_mkdir,
- .vop_mknod = nfs_mknod,
- .vop_open = nfs_open,
- .vop_print = nfs_print,
- .vop_read = nfs_read,
- .vop_readdir = nfs_readdir,
- .vop_readlink = nfs_readlink,
- .vop_reclaim = nfs_reclaim,
- .vop_remove = nfs_remove,
- .vop_rename = nfs_rename,
- .vop_rmdir = nfs_rmdir,
- .vop_setattr = nfs_setattr,
- .vop_strategy = nfs_strategy,
- .vop_symlink = nfs_symlink,
- .vop_write = nfs_write,
-};
-
-struct vop_vector nfs_fifoops = {
- .vop_default = &fifo_specops,
- .vop_access = nfsspec_access,
- .vop_close = nfsfifo_close,
- .vop_fsync = nfs_fsync,
- .vop_getattr = nfs_getattr,
- .vop_inactive = nfs_inactive,
- .vop_print = nfs_print,
- .vop_read = nfsfifo_read,
- .vop_reclaim = nfs_reclaim,
- .vop_setattr = nfs_setattr,
- .vop_write = nfsfifo_write,
-};
-
-static int nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp,
- struct componentname *cnp, struct vattr *vap);
-static int nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
- struct ucred *cred, struct thread *td);
-static int nfs_renamerpc(struct vnode *fdvp, const char *fnameptr,
- int fnamelen, struct vnode *tdvp,
- const char *tnameptr, int tnamelen,
- struct ucred *cred, struct thread *td);
-static int nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
- struct sillyrename *sp);
-
-/*
- * Global variables
- */
-struct mtx nfs_iod_mtx;
-enum nfsiod_state nfs_iodwant[NFS_MAXASYNCDAEMON];
-struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
-int nfs_numasync = 0;
-#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
-
-SYSCTL_DECL(_vfs_oldnfs);
-
-static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
- &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
-
-static int nfs_prime_access_cache = 0;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, prime_access_cache, CTLFLAG_RW,
- &nfs_prime_access_cache, 0,
- "Prime NFS ACCESS cache when fetching attributes");
-
-static int nfsv3_commit_on_close = 0;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
- &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
-
-static int nfs_clean_pages_on_close = 1;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, clean_pages_on_close, CTLFLAG_RW,
- &nfs_clean_pages_on_close, 0, "NFS clean dirty pages on close");
-
-int nfs_directio_enable = 0;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_directio_enable, CTLFLAG_RW,
- &nfs_directio_enable, 0, "Enable NFS directio");
-
-/*
- * This sysctl allows other processes to mmap a file that has been opened
- * O_DIRECT by a process. In general, having processes mmap the file while
- * Direct IO is in progress can lead to Data Inconsistencies. But, we allow
- * this by default to prevent DoS attacks - to prevent a malicious user from
- * opening up files O_DIRECT preventing other users from mmap'ing these
- * files. "Protected" environments where stricter consistency guarantees are
- * required can disable this knob. The process that opened the file O_DIRECT
- * cannot mmap() the file, because mmap'ed IO on an O_DIRECT open() is not
- * meaningful.
- */
-int nfs_directio_allow_mmap = 1;
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, nfs_directio_allow_mmap, CTLFLAG_RW,
- &nfs_directio_allow_mmap, 0, "Enable mmaped IO on file with O_DIRECT opens");
-
-#if 0
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
- &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
-
-SYSCTL_INT(_vfs_oldnfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
- &nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count");
-#endif
-
-#define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
- | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
- | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
-
-/*
- * SMP Locking Note :
- * The list of locks after the description of the lock is the ordering
- * of other locks acquired with the lock held.
- * np->n_mtx : Protects the fields in the nfsnode.
- VM Object Lock
- VI_MTX (acquired indirectly)
- * nmp->nm_mtx : Protects the fields in the nfsmount.
- rep->r_mtx
- * nfs_iod_mtx : Global lock, protects shared nfsiod state.
- * nfs_reqq_mtx : Global lock, protects the nfs_reqq list.
- nmp->nm_mtx
- rep->r_mtx
- * rep->r_mtx : Protects the fields in an nfsreq.
- */
-
-static int
-nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
- struct ucred *cred, uint32_t *retmode)
-{
- const int v3 = 1;
- u_int32_t *tl;
- int error = 0, attrflag, i, lrupos;
-
- struct mbuf *mreq, *mrep, *md, *mb;
- caddr_t bpos, dpos;
- u_int32_t rmode;
- struct nfsnode *np = VTONFS(vp);
-
- nfsstats.rpccnt[NFSPROC_ACCESS]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED, M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(wmode);
- nfsm_request(vp, NFSPROC_ACCESS, td, cred);
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- lrupos = 0;
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- rmode = fxdr_unsigned(u_int32_t, *tl);
- mtx_lock(&np->n_mtx);
- for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
- if (np->n_accesscache[i].uid == cred->cr_uid) {
- np->n_accesscache[i].mode = rmode;
- np->n_accesscache[i].stamp = time_second;
- break;
- }
- if (i > 0 && np->n_accesscache[i].stamp <
- np->n_accesscache[lrupos].stamp)
- lrupos = i;
- }
- if (i == NFS_ACCESSCACHESIZE) {
- np->n_accesscache[lrupos].uid = cred->cr_uid;
- np->n_accesscache[lrupos].mode = rmode;
- np->n_accesscache[lrupos].stamp = time_second;
- }
- mtx_unlock(&np->n_mtx);
- if (retmode != NULL)
- *retmode = rmode;
- KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0);
- }
- m_freem(mrep);
-nfsmout:
-#ifdef KDTRACE_HOOKS
- if (error) {
- KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0,
- error);
- }
-#endif
- return (error);
-}
-
-/*
- * nfs access vnode op.
- * For nfs version 2, just return ok. File accesses may fail later.
- * For nfs version 3, use the access rpc to check accessibility. If file modes
- * are changed on the server, accesses might still fail later.
- */
-static int
-nfs_access(struct vop_access_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- int error = 0, i, gotahit;
- u_int32_t mode, rmode, wmode;
- int v3 = NFS_ISV3(vp);
- struct nfsnode *np = VTONFS(vp);
-
- /*
- * Disallow write attempts on filesystems mounted read-only;
- * unless the file is a socket, fifo, or a block or character
- * device resident on the filesystem.
- */
- if ((ap->a_accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
- /*
- * For nfs v3, check to see if we have done this recently, and if
- * so return our cached result instead of making an ACCESS call.
- * If not, do an access rpc, otherwise you are stuck emulating
- * ufs_access() locally using the vattr. This may not be correct,
- * since the server may apply other access criteria such as
- * client uid-->server uid mapping that we do not know about.
- */
- if (v3) {
- if (ap->a_accmode & VREAD)
- mode = NFSV3ACCESS_READ;
- else
- mode = 0;
- if (vp->v_type != VDIR) {
- if (ap->a_accmode & VWRITE)
- mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
- if (ap->a_accmode & VEXEC)
- mode |= NFSV3ACCESS_EXECUTE;
- } else {
- if (ap->a_accmode & VWRITE)
- mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
- NFSV3ACCESS_DELETE);
- if (ap->a_accmode & VEXEC)
- mode |= NFSV3ACCESS_LOOKUP;
- }
- /* XXX safety belt, only make blanket request if caching */
- if (nfsaccess_cache_timeout > 0) {
- wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
- NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
- NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
- } else {
- wmode = mode;
- }
-
- /*
- * Does our cached result allow us to give a definite yes to
- * this request?
- */
- gotahit = 0;
- mtx_lock(&np->n_mtx);
- for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
- if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) {
- if (time_second < (np->n_accesscache[i].stamp +
- nfsaccess_cache_timeout) &&
- (np->n_accesscache[i].mode & mode) == mode) {
- nfsstats.accesscache_hits++;
- gotahit = 1;
- }
- break;
- }
- }
- mtx_unlock(&np->n_mtx);
-#ifdef KDTRACE_HOOKS
- if (gotahit)
- KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp,
- ap->a_cred->cr_uid, mode);
- else
- KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp,
- ap->a_cred->cr_uid, mode);
-#endif
- if (gotahit == 0) {
- /*
- * Either a no, or a don't know. Go to the wire.
- */
- nfsstats.accesscache_misses++;
- error = nfs3_access_otw(vp, wmode, ap->a_td, ap->a_cred,
- &rmode);
- if (!error) {
- if ((rmode & mode) != mode)
- error = EACCES;
- }
- }
- return (error);
- } else {
- if ((error = nfsspec_access(ap)) != 0) {
- return (error);
- }
- /*
- * Attempt to prevent a mapped root from accessing a file
- * which it shouldn't. We try to read a byte from the file
- * if the user is root and the file is not zero length.
- * After calling nfsspec_access, we should have the correct
- * file size cached.
- */
- mtx_lock(&np->n_mtx);
- if (ap->a_cred->cr_uid == 0 && (ap->a_accmode & VREAD)
- && VTONFS(vp)->n_size > 0) {
- struct iovec aiov;
- struct uio auio;
- char buf[1];
-
- mtx_unlock(&np->n_mtx);
- aiov.iov_base = buf;
- aiov.iov_len = 1;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_resid = 1;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- auio.uio_td = ap->a_td;
-
- if (vp->v_type == VREG)
- error = nfs_readrpc(vp, &auio, ap->a_cred);
- else if (vp->v_type == VDIR) {
- char* bp;
- bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
- aiov.iov_base = bp;
- aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
- error = nfs_readdirrpc(vp, &auio, ap->a_cred);
- free(bp, M_TEMP);
- } else if (vp->v_type == VLNK)
- error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
- else
- error = EACCES;
- } else
- mtx_unlock(&np->n_mtx);
- return (error);
- }
-}
-
-int nfs_otw_getattr_avoid = 0;
-
-/*
- * nfs open vnode op
- * Check to see if the type is ok
- * and that deletion is not in progress.
- * For paged in text files, you will need to flush the page cache
- * if consistency is lost.
- */
-/* ARGSUSED */
-static int
-nfs_open(struct vop_open_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct vattr vattr;
- int error;
- int fmode = ap->a_mode;
- struct ucred *cred;
-
- if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
- return (EOPNOTSUPP);
-
- /*
- * Get a valid lease. If cached data is stale, flush it.
- */
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NMODIFIED) {
- mtx_unlock(&np->n_mtx);
- error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
- if (error == EINTR || error == EIO)
- return (error);
- mtx_lock(&np->n_mtx);
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- if (vp->v_type == VDIR)
- np->n_direofoffset = 0;
- mtx_unlock(&np->n_mtx);
- error = VOP_GETATTR(vp, &vattr, ap->a_cred);
- if (error)
- return (error);
- mtx_lock(&np->n_mtx);
- np->n_mtime = vattr.va_mtime;
- } else {
- mtx_unlock(&np->n_mtx);
- error = VOP_GETATTR(vp, &vattr, ap->a_cred);
- if (error)
- return (error);
- mtx_lock(&np->n_mtx);
- if (NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
- if (vp->v_type == VDIR)
- np->n_direofoffset = 0;
- mtx_unlock(&np->n_mtx);
- error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
- if (error == EINTR || error == EIO) {
- return (error);
- }
- mtx_lock(&np->n_mtx);
- np->n_mtime = vattr.va_mtime;
- }
- }
- /*
- * If the object has >= 1 O_DIRECT active opens, we disable caching.
- */
- if (nfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
- if (np->n_directio_opens == 0) {
- mtx_unlock(&np->n_mtx);
- error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
- if (error)
- return (error);
- mtx_lock(&np->n_mtx);
- np->n_flag |= NNONCACHE;
- }
- np->n_directio_opens++;
- }
-
- /*
- * If this is an open for writing, capture a reference to the
- * credentials, so they can be used by nfs_putpages(). Using
- * these write credentials is preferable to the credentials of
- * whatever thread happens to be doing the VOP_PUTPAGES() since
- * the write RPCs are less likely to fail with EACCES.
- */
- if ((fmode & FWRITE) != 0) {
- cred = np->n_writecred;
- np->n_writecred = crhold(ap->a_cred);
- } else
- cred = NULL;
- mtx_unlock(&np->n_mtx);
- if (cred != NULL)
- crfree(cred);
- vnode_create_vobject(vp, vattr.va_size, ap->a_td);
- return (0);
-}
-
-/*
- * nfs close vnode op
- * What an NFS client should do upon close after writing is a debatable issue.
- * Most NFS clients push delayed writes to the server upon close, basically for
- * two reasons:
- * 1 - So that any write errors may be reported back to the client process
- * doing the close system call. By far the two most likely errors are
- * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
- * 2 - To put a worst case upper bound on cache inconsistency between
- * multiple clients for the file.
- * There is also a consistency problem for Version 2 of the protocol w.r.t.
- * not being able to tell if other clients are writing a file concurrently,
- * since there is no way of knowing if the changed modify time in the reply
- * is only due to the write for this client.
- * (NFS Version 3 provides weak cache consistency data in the reply that
- * should be sufficient to detect and handle this case.)
- *
- * The current code does the following:
- * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
- * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
- * or commit them (this satisfies 1 and 2 except for the
- * case where the server crashes after this close but
- * before the commit RPC, which is felt to be "good
- * enough". Changing the last argument to nfs_flush() to
- * a 1 would force a commit operation, if it is felt a
- * commit is necessary now.
- */
-/* ARGSUSED */
-static int
-nfs_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- int error = 0;
- int fmode = ap->a_fflag;
-
- if (vp->v_type == VREG) {
- /*
- * Examine and clean dirty pages, regardless of NMODIFIED.
- * This closes a major hole in close-to-open consistency.
- * We want to push out all dirty pages (and buffers) on
- * close, regardless of whether they were dirtied by
- * mmap'ed writes or via write().
- */
- if (nfs_clean_pages_on_close && vp->v_object) {
- VM_OBJECT_WLOCK(vp->v_object);
- vm_object_page_clean(vp->v_object, 0, 0, 0);
- VM_OBJECT_WUNLOCK(vp->v_object);
- }
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NMODIFIED) {
- mtx_unlock(&np->n_mtx);
- if (NFS_ISV3(vp)) {
- /*
- * Under NFSv3 we have dirty buffers to dispose of. We
- * must flush them to the NFS server. We have the option
- * of waiting all the way through the commit rpc or just
- * waiting for the initial write. The default is to only
- * wait through the initial write so the data is in the
- * server's cache, which is roughly similar to the state
- * a standard disk subsystem leaves the file in on close().
- *
- * We cannot clear the NMODIFIED bit in np->n_flag due to
- * potential races with other processes, and certainly
- * cannot clear it if we don't commit.
- */
- int cm = nfsv3_commit_on_close ? 1 : 0;
- error = nfs_flush(vp, MNT_WAIT, cm);
- /* np->n_flag &= ~NMODIFIED; */
- } else
- error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
- mtx_lock(&np->n_mtx);
- }
- if (np->n_flag & NWRITEERR) {
- np->n_flag &= ~NWRITEERR;
- error = np->n_error;
- }
- mtx_unlock(&np->n_mtx);
- }
- if (nfs_directio_enable)
- KASSERT((np->n_directio_asyncwr == 0),
- ("nfs_close: dirty unflushed (%d) directio buffers\n",
- np->n_directio_asyncwr));
- if (nfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
- mtx_lock(&np->n_mtx);
- KASSERT((np->n_directio_opens > 0),
- ("nfs_close: unexpectedly value (0) of n_directio_opens\n"));
- np->n_directio_opens--;
- if (np->n_directio_opens == 0)
- np->n_flag &= ~NNONCACHE;
- mtx_unlock(&np->n_mtx);
- }
- return (error);
-}
-
-/*
- * nfs getattr call from vfs.
- */
-static int
-nfs_getattr(struct vop_getattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct thread *td = curthread;
- struct vattr *vap = ap->a_vap;
- struct vattr vattr;
- caddr_t bpos, dpos;
- int error = 0;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(vp);
-
- /*
- * Update local times for special files.
- */
- mtx_lock(&np->n_mtx);
- if (np->n_flag & (NACC | NUPD))
- np->n_flag |= NCHG;
- mtx_unlock(&np->n_mtx);
- /*
- * First look in the cache.
- */
- if (nfs_getattrcache(vp, &vattr) == 0)
- goto nfsmout;
- if (v3 && nfs_prime_access_cache && nfsaccess_cache_timeout > 0) {
- nfsstats.accesscache_misses++;
- nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, ap->a_cred, NULL);
- if (nfs_getattrcache(vp, &vattr) == 0)
- goto nfsmout;
- }
- nfsstats.rpccnt[NFSPROC_GETATTR]++;
- mreq = m_get2(NFSX_FH(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_GETATTR, td, ap->a_cred);
- if (!error) {
- nfsm_loadattr(vp, &vattr);
- }
- m_freem(mrep);
-nfsmout:
- vap->va_type = vattr.va_type;
- vap->va_mode = vattr.va_mode;
- vap->va_nlink = vattr.va_nlink;
- vap->va_uid = vattr.va_uid;
- vap->va_gid = vattr.va_gid;
- vap->va_fsid = vattr.va_fsid;
- vap->va_fileid = vattr.va_fileid;
- vap->va_size = vattr.va_size;
- vap->va_blocksize = vattr.va_blocksize;
- vap->va_atime = vattr.va_atime;
- vap->va_mtime = vattr.va_mtime;
- vap->va_ctime = vattr.va_ctime;
- vap->va_gen = vattr.va_gen;
- vap->va_flags = vattr.va_flags;
- vap->va_rdev = vattr.va_rdev;
- vap->va_bytes = vattr.va_bytes;
- vap->va_filerev = vattr.va_filerev;
-
- return (error);
-}
-
-/*
- * nfs setattr call.
- */
-static int
-nfs_setattr(struct vop_setattr_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct vattr *vap = ap->a_vap;
- struct thread *td = curthread;
- int error = 0;
- u_quad_t tsize;
-
-#ifndef nolint
- tsize = (u_quad_t)0;
-#endif
-
- /*
- * Setting of flags is not supported.
- */
- if (vap->va_flags != VNOVAL)
- return (EOPNOTSUPP);
-
- /*
- * Disallow write attempts if the filesystem is mounted read-only.
- */
- if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
- vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
- vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
- (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- error = EROFS;
- goto out;
- }
- if (vap->va_size != VNOVAL) {
- switch (vp->v_type) {
- case VDIR:
- return (EISDIR);
- case VCHR:
- case VBLK:
- case VSOCK:
- case VFIFO:
- if (vap->va_mtime.tv_sec == VNOVAL &&
- vap->va_atime.tv_sec == VNOVAL &&
- vap->va_mode == (mode_t)VNOVAL &&
- vap->va_uid == (uid_t)VNOVAL &&
- vap->va_gid == (gid_t)VNOVAL)
- return (0);
- vap->va_size = VNOVAL;
- break;
- default:
- /*
- * Disallow write attempts if the filesystem is
- * mounted read-only.
- */
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- /*
- * We run vnode_pager_setsize() early (why?),
- * we must set np->n_size now to avoid vinvalbuf
- * V_SAVE races that might setsize a lower
- * value.
- */
- mtx_lock(&np->n_mtx);
- tsize = np->n_size;
- mtx_unlock(&np->n_mtx);
- error = nfs_meta_setsize(vp, ap->a_cred, td,
- vap->va_size);
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NMODIFIED) {
- tsize = np->n_size;
- mtx_unlock(&np->n_mtx);
- if (vap->va_size == 0)
- error = nfs_vinvalbuf(vp, 0, td, 1);
- else
- error = nfs_vinvalbuf(vp, V_SAVE, td, 1);
- if (error) {
- vnode_pager_setsize(vp, tsize);
- goto out;
- }
- } else
- mtx_unlock(&np->n_mtx);
- /*
- * np->n_size has already been set to vap->va_size
- * in nfs_meta_setsize(). We must set it again since
- * nfs_loadattrcache() could be called through
- * nfs_meta_setsize() and could modify np->n_size.
- */
- mtx_lock(&np->n_mtx);
- np->n_vattr.va_size = np->n_size = vap->va_size;
- mtx_unlock(&np->n_mtx);
- };
- } else {
- mtx_lock(&np->n_mtx);
- if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) &&
- (np->n_flag & NMODIFIED) && vp->v_type == VREG) {
- mtx_unlock(&np->n_mtx);
- if ((error = nfs_vinvalbuf(vp, V_SAVE, td, 1)) != 0 &&
- (error == EINTR || error == EIO))
- return error;
- } else
- mtx_unlock(&np->n_mtx);
- }
- error = nfs_setattrrpc(vp, vap, ap->a_cred);
- if (error && vap->va_size != VNOVAL) {
- mtx_lock(&np->n_mtx);
- np->n_size = np->n_vattr.va_size = tsize;
- vnode_pager_setsize(vp, tsize);
- mtx_unlock(&np->n_mtx);
- }
-out:
- return (error);
-}
-
-/*
- * Do an nfs setattr rpc.
- */
-static int
-nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred)
-{
- struct nfsv2_sattr *sp;
- struct nfsnode *np = VTONFS(vp);
- caddr_t bpos, dpos;
- u_int32_t *tl;
- int error = 0, i, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(vp);
-
- nfsstats.rpccnt[NFSPROC_SETATTR]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_SATTR(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- if (v3) {
- nfsm_v3attrbuild(vap, TRUE);
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = nfs_false;
- } else {
- sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
- if (vap->va_mode == (mode_t)VNOVAL)
- sp->sa_mode = nfs_xdrneg1;
- else
- sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
- if (vap->va_uid == (uid_t)VNOVAL)
- sp->sa_uid = nfs_xdrneg1;
- else
- sp->sa_uid = txdr_unsigned(vap->va_uid);
- if (vap->va_gid == (gid_t)VNOVAL)
- sp->sa_gid = nfs_xdrneg1;
- else
- sp->sa_gid = txdr_unsigned(vap->va_gid);
- sp->sa_size = txdr_unsigned(vap->va_size);
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(vp, NFSPROC_SETATTR, curthread, cred);
- if (v3) {
- mtx_lock(&np->n_mtx);
- for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
- np->n_accesscache[i].stamp = 0;
- mtx_unlock(&np->n_mtx);
- KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
- nfsm_wcc_data(vp, wccflag);
- } else
- nfsm_loadattr(vp, NULL);
- m_freem(mrep);
-nfsmout:
- return (error);
-}
-
-/*
- * nfs lookup call, one step at a time...
- * First look in cache
- * If not found, unlock the directory nfsnode and do the rpc
- */
-static int
-nfs_lookup(struct vop_lookup_args *ap)
-{
- struct componentname *cnp = ap->a_cnp;
- struct vnode *dvp = ap->a_dvp;
- struct vnode **vpp = ap->a_vpp;
- struct mount *mp = dvp->v_mount;
- struct vattr dvattr, vattr;
- struct timespec nctime;
- int flags = cnp->cn_flags;
- struct vnode *newvp;
- struct nfsmount *nmp;
- caddr_t bpos, dpos;
- struct mbuf *mreq, *mrep, *md, *mb;
- long len;
- nfsfh_t *fhp;
- struct nfsnode *np, *newnp;
- int error = 0, attrflag, dattrflag, fhsize, ltype, ncticks;
- int v3 = NFS_ISV3(dvp);
- struct thread *td = cnp->cn_thread;
-
- *vpp = NULLVP;
- if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
- return (EROFS);
- if (dvp->v_type != VDIR)
- return (ENOTDIR);
- nmp = VFSTONFS(mp);
- np = VTONFS(dvp);
- if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) {
- *vpp = NULLVP;
- return (error);
- }
- error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks);
- if (error > 0 && error != ENOENT)
- return (error);
- if (error == -1) {
- /*
- * Lookups of "." are special and always return the
- * current directory. cache_lookup() already handles
- * associated locking bookkeeping, etc.
- */
- if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
- /* XXX: Is this really correct? */
- if (cnp->cn_nameiop != LOOKUP &&
- (flags & ISLASTCN))
- cnp->cn_flags |= SAVENAME;
- return (0);
- }
-
- /*
- * We only accept a positive hit in the cache if the
- * change time of the file matches our cached copy.
- * Otherwise, we discard the cache entry and fallback
- * to doing a lookup RPC. We also only trust cache
- * entries for less than nm_nametimeo seconds.
- *
- * To better handle stale file handles and attributes,
- * clear the attribute cache of this node if it is a
- * leaf component, part of an open() call, and not
- * locally modified before fetching the attributes.
- * This should allow stale file handles to be detected
- * here where we can fall back to a LOOKUP RPC to
- * recover rather than having nfs_open() detect the
- * stale file handle and failing open(2) with ESTALE.
- */
- newvp = *vpp;
- newnp = VTONFS(newvp);
- if (!(nmp->nm_flag & NFSMNT_NOCTO) &&
- (flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
- !(newnp->n_flag & NMODIFIED)) {
- mtx_lock(&newnp->n_mtx);
- newnp->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
- mtx_unlock(&newnp->n_mtx);
- }
- if ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) &&
- VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
- timespeccmp(&vattr.va_ctime, &nctime, ==)) {
- nfsstats.lookupcache_hits++;
- if (cnp->cn_nameiop != LOOKUP &&
- (flags & ISLASTCN))
- cnp->cn_flags |= SAVENAME;
- return (0);
- }
- cache_purge(newvp);
- if (dvp != newvp)
- vput(newvp);
- else
- vrele(newvp);
- *vpp = NULLVP;
- } else if (error == ENOENT) {
- if (dvp->v_iflag & VI_DOOMED)
- return (ENOENT);
- /*
- * We only accept a negative hit in the cache if the
- * modification time of the parent directory matches
- * the cached copy in the name cache entry.
- * Otherwise, we discard all of the negative cache
- * entries for this directory. We also only trust
- * negative cache entries for up to nm_negnametimeo
- * seconds.
- */
- if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) &&
- VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
- timespeccmp(&vattr.va_mtime, &nctime, ==)) {
- nfsstats.lookupcache_hits++;
- return (ENOENT);
- }
- cache_purge_negative(dvp);
- }
-
- attrflag = dattrflag = 0;
- error = 0;
- newvp = NULLVP;
- nfsstats.lookupcache_misses++;
- nfsstats.rpccnt[NFSPROC_LOOKUP]++;
- len = cnp->cn_namelen;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len), M_WAITOK,
- MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred);
- if (error) {
- if (v3) {
- nfsm_postop_attr_va(dvp, dattrflag, &vattr);
- m_freem(mrep);
- }
- goto nfsmout;
- }
- nfsm_getfh(fhp, fhsize, v3);
-
- /*
- * Handle RENAME case...
- */
- if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN)) {
- if (NFS_CMPFH(np, fhp, fhsize)) {
- m_freem(mrep);
- return (EISDIR);
- }
- error = nfs_nget(mp, fhp, fhsize, &np, LK_EXCLUSIVE);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- newvp = NFSTOV(np);
- if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- nfsm_postop_attr(dvp, attrflag);
- } else
- nfsm_loadattr(newvp, NULL);
- *vpp = newvp;
- m_freem(mrep);
- cnp->cn_flags |= SAVENAME;
- return (0);
- }
-
- if (flags & ISDOTDOT) {
- ltype = VOP_ISLOCKED(dvp);
- error = vfs_busy(mp, MBF_NOWAIT);
- if (error != 0) {
- vfs_ref(mp);
- VOP_UNLOCK(dvp, 0);
- error = vfs_busy(mp, 0);
- vn_lock(dvp, ltype | LK_RETRY);
- vfs_rel(mp);
- if (error == 0 && (dvp->v_iflag & VI_DOOMED)) {
- vfs_unbusy(mp);
- error = ENOENT;
- }
- if (error != 0) {
- m_freem(mrep);
- return (error);
- }
- }
- VOP_UNLOCK(dvp, 0);
- error = nfs_nget(mp, fhp, fhsize, &np, cnp->cn_lkflags);
- if (error == 0)
- newvp = NFSTOV(np);
- vfs_unbusy(mp);
- if (newvp != dvp)
- vn_lock(dvp, ltype | LK_RETRY);
- if (dvp->v_iflag & VI_DOOMED) {
- if (error == 0) {
- if (newvp == dvp)
- vrele(newvp);
- else
- vput(newvp);
- }
- error = ENOENT;
- }
- if (error) {
- m_freem(mrep);
- return (error);
- }
- } else if (NFS_CMPFH(np, fhp, fhsize)) {
- VREF(dvp);
- newvp = dvp;
- } else {
- error = nfs_nget(mp, fhp, fhsize, &np, cnp->cn_lkflags);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- newvp = NFSTOV(np);
-
- /*
- * Flush the attribute cache when opening a leaf node
- * to ensure that fresh attributes are fetched in
- * nfs_open() if we are unable to fetch attributes
- * from the LOOKUP reply.
- */
- if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
- !(np->n_flag & NMODIFIED)) {
- mtx_lock(&np->n_mtx);
- np->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
- mtx_unlock(&np->n_mtx);
- }
- }
- if (v3) {
- nfsm_postop_attr_va(newvp, attrflag, &vattr);
- nfsm_postop_attr_va(dvp, dattrflag, &dvattr);
- } else {
- nfsm_loadattr(newvp, &vattr);
- attrflag = 1;
- }
- if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
- cnp->cn_flags |= SAVENAME;
- if ((cnp->cn_flags & MAKEENTRY) &&
- (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) &&
- attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0))
- cache_enter_time(dvp, newvp, cnp, &vattr.va_ctime,
- newvp->v_type != VDIR ? NULL : &dvattr.va_ctime);
- *vpp = newvp;
- m_freem(mrep);
-nfsmout:
- if (error) {
- if (newvp != NULLVP) {
- vput(newvp);
- *vpp = NULLVP;
- }
-
- if (error != ENOENT)
- goto done;
-
- /* The requested file was not found. */
- if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
- (flags & ISLASTCN)) {
- /*
- * XXX: UFS does a full VOP_ACCESS(dvp,
- * VWRITE) here instead of just checking
- * MNT_RDONLY.
- */
- if (mp->mnt_flag & MNT_RDONLY)
- return (EROFS);
- cnp->cn_flags |= SAVENAME;
- return (EJUSTRETURN);
- }
-
- if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) {
- /*
- * Cache the modification time of the parent
- * directory from the post-op attributes in
- * the name cache entry. The negative cache
- * entry will be ignored once the directory
- * has changed. Don't bother adding the entry
- * if the directory has already changed.
- */
- mtx_lock(&np->n_mtx);
- if (timespeccmp(&np->n_vattr.va_mtime,
- &vattr.va_mtime, ==)) {
- mtx_unlock(&np->n_mtx);
- cache_enter_time(dvp, NULL, cnp,
- &vattr.va_mtime, NULL);
- } else
- mtx_unlock(&np->n_mtx);
- }
- return (ENOENT);
- }
-done:
- return (error);
-}
-
-/*
- * nfs read call.
- * Just call nfs_bioread() to do the work.
- */
-static int
-nfs_read(struct vop_read_args *ap)
-{
- struct vnode *vp = ap->a_vp;
-
- switch (vp->v_type) {
- case VREG:
- return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
- case VDIR:
- return (EISDIR);
- default:
- return (EOPNOTSUPP);
- }
-}
-
-/*
- * nfs readlink call
- */
-static int
-nfs_readlink(struct vop_readlink_args *ap)
-{
- struct vnode *vp = ap->a_vp;
-
- if (vp->v_type != VLNK)
- return (EINVAL);
- return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
-}
-
-/*
- * Do a readlink rpc.
- * Called by nfs_doio() from below the buffer cache.
- */
-int
-nfs_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
-{
- caddr_t bpos, dpos;
- int error = 0, len, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(vp);
-
- nfsstats.rpccnt[NFSPROC_READLINK]++;
- mreq = m_get2(NFSX_FH(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, cred);
- if (v3)
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- nfsm_strsiz(len, NFS_MAXPATHLEN);
- if (len == NFS_MAXPATHLEN) {
- struct nfsnode *np = VTONFS(vp);
- mtx_lock(&np->n_mtx);
- if (np->n_size && np->n_size < NFS_MAXPATHLEN)
- len = np->n_size;
- mtx_unlock(&np->n_mtx);
- }
- nfsm_mtouio(uiop, len);
- }
- m_freem(mrep);
-nfsmout:
- return (error);
-}
-
-/*
- * nfs read rpc call
- * Ditto above
- */
-int
-nfs_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
-{
- u_int32_t *tl;
- caddr_t bpos, dpos;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct nfsmount *nmp;
- off_t end;
- int error = 0, len, retlen, tsiz, eof, attrflag;
- int v3 = NFS_ISV3(vp);
- int rsize;
-
-#ifndef nolint
- eof = 0;
-#endif
- nmp = VFSTONFS(vp->v_mount);
- tsiz = uiop->uio_resid;
- mtx_lock(&nmp->nm_mtx);
- end = uiop->uio_offset + tsiz;
- if (end > nmp->nm_maxfilesize || end < uiop->uio_offset) {
- mtx_unlock(&nmp->nm_mtx);
- return (EFBIG);
- }
- rsize = nmp->nm_rsize;
- mtx_unlock(&nmp->nm_mtx);
- while (tsiz > 0) {
- nfsstats.rpccnt[NFSPROC_READ]++;
- len = (tsiz > rsize) ? rsize : tsiz;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED * 3, M_WAITOK,
- MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED * 3);
- if (v3) {
- txdr_hyper(uiop->uio_offset, tl);
- *(tl + 2) = txdr_unsigned(len);
- } else {
- *tl++ = txdr_unsigned(uiop->uio_offset);
- *tl++ = txdr_unsigned(len);
- *tl = 0;
- }
- nfsm_request(vp, NFSPROC_READ, uiop->uio_td, cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- if (error) {
- m_freem(mrep);
- goto nfsmout;
- }
- tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
- eof = fxdr_unsigned(int, *(tl + 1));
- } else {
- nfsm_loadattr(vp, NULL);
- }
- nfsm_strsiz(retlen, rsize);
- nfsm_mtouio(uiop, retlen);
- m_freem(mrep);
- tsiz -= retlen;
- if (v3) {
- if (eof || retlen == 0) {
- tsiz = 0;
- }
- } else if (retlen < len) {
- tsiz = 0;
- }
- }
-nfsmout:
- return (error);
-}
-
-/*
- * nfs write call
- */
-int
-nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
- int *iomode, int *must_commit)
-{
- u_int32_t *tl;
- int32_t backup;
- caddr_t bpos, dpos;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- off_t end;
- int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
- int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
- int wsize;
-
- KASSERT(uiop->uio_iovcnt == 1, ("nfs: writerpc iovcnt > 1"));
- *must_commit = 0;
- tsiz = uiop->uio_resid;
- mtx_lock(&nmp->nm_mtx);
- end = uiop->uio_offset + tsiz;
- if (end > nmp->nm_maxfilesize || end < uiop->uio_offset) {
- mtx_unlock(&nmp->nm_mtx);
- return (EFBIG);
- }
- wsize = nmp->nm_wsize;
- mtx_unlock(&nmp->nm_mtx);
- while (tsiz > 0) {
- nfsstats.rpccnt[NFSPROC_WRITE]++;
- len = (tsiz > wsize) ? wsize : tsiz;
- mreq = m_get2(NFSX_FH(v3) + 5 * NFSX_UNSIGNED, M_WAITOK,
- MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- if (v3) {
- tl = nfsm_build(u_int32_t *, 5 * 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;
-
- tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
- /* 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_uiotom(uiop, len);
- nfsm_request(vp, NFSPROC_WRITE, uiop->uio_td, cred);
- if (v3) {
- wccflag = NFSV3_WCCCHK;
- nfsm_wcc_data(vp, wccflag);
- if (!error) {
- tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED
- + NFSX_V3WRITEVERF);
- rlen = fxdr_unsigned(int, *tl++);
- if (rlen == 0) {
- error = NFSERR_IO;
- m_freem(mrep);
- break;
- } 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 committment level
- * obtained by any of the RPCs.
- */
- if (committed == NFSV3WRITE_FILESYNC)
- committed = commit;
- else if (committed == NFSV3WRITE_DATASYNC &&
- commit == NFSV3WRITE_UNSTABLE)
- committed = commit;
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- nmp->nm_state |= NFSSTA_HASWRITEVERF;
- } else if (bcmp((caddr_t)tl,
- (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
- *must_commit = 1;
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- }
- mtx_unlock(&nmp->nm_mtx);
- }
- } else {
- nfsm_loadattr(vp, NULL);
- }
- if (wccflag) {
- mtx_lock(&(VTONFS(vp))->n_mtx);
- VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime;
- mtx_unlock(&(VTONFS(vp))->n_mtx);
- }
- m_freem(mrep);
- if (error)
- break;
- tsiz -= len;
- }
-nfsmout:
- if (DOINGASYNC(vp))
- committed = NFSV3WRITE_FILESYNC;
- *iomode = committed;
- if (error)
- uiop->uio_resid = tsiz;
- 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.
- */
-static int
-nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
- struct vattr *vap)
-{
- struct nfsv2_sattr *sp;
- u_int32_t *tl;
- struct vnode *newvp = NULL;
- struct nfsnode *np = NULL;
- struct vattr vattr;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb;
- u_int32_t rdev;
- int v3 = NFS_ISV3(dvp);
-
- if (vap->va_type == VCHR || vap->va_type == VBLK)
- rdev = txdr_unsigned(vap->va_rdev);
- else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
- rdev = nfs_xdrneg1;
- else {
- return (EOPNOTSUPP);
- }
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0)
- return (error);
- nfsstats.rpccnt[NFSPROC_MKNOD]++;
- mreq = m_get2(NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl++ = vtonfsv3_type(vap->va_type);
- nfsm_v3attrbuild(vap, FALSE);
- if (vap->va_type == VCHR || vap->va_type == VBLK) {
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(major(vap->va_rdev));
- *tl = txdr_unsigned(minor(vap->va_rdev));
- }
- } else {
- sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = rdev;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_thread, cnp->cn_cred);
- if (!error) {
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (!gotvp) {
- if (newvp) {
- vput(newvp);
- newvp = NULL;
- }
- error = nfs_lookitup(dvp, cnp->cn_nameptr,
- cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- }
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- m_freem(mrep);
-nfsmout:
- if (error) {
- if (newvp)
- vput(newvp);
- } else {
- *vpp = newvp;
- }
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- return (error);
-}
-
-/*
- * nfs mknod vop
- * just call nfs_mknodrpc() to do the work.
- */
-/* ARGSUSED */
-static int
-nfs_mknod(struct vop_mknod_args *ap)
-{
- return (nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap));
-}
-
-static u_long create_verf;
-/*
- * nfs file create call
- */
-static int
-nfs_create(struct vop_create_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vattr *vap = ap->a_vap;
- struct componentname *cnp = ap->a_cnp;
- struct nfsv2_sattr *sp;
- u_int32_t *tl;
- struct nfsnode *np = NULL;
- struct vnode *newvp = NULL;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct vattr vattr;
- int v3 = NFS_ISV3(dvp);
-
- /*
- * Oops, not for me..
- */
- if (vap->va_type == VSOCK) {
- error = nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap);
- return (error);
- }
-
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0) {
- return (error);
- }
- if (vap->va_vaflags & VA_EXCLUSIVE)
- fmode |= O_EXCL;
-again:
- nfsstats.rpccnt[NFSPROC_CREATE]++;
- mreq = m_get2(NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- if (fmode & O_EXCL) {
- *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
- tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF);
-#ifdef INET
- CURVNET_SET(CRED_TO_VNET(cnp->cn_cred));
- IN_IFADDR_RLOCK();
- if (!TAILQ_EMPTY(&V_in_ifaddrhead))
- *tl++ = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
- else
-#endif
- *tl++ = create_verf;
-#ifdef INET
- IN_IFADDR_RUNLOCK();
- CURVNET_RESTORE();
-#endif
- *tl = ++create_verf;
- } else {
- *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
- nfsm_v3attrbuild(vap, FALSE);
- }
- } else {
- sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = 0;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_thread, cnp->cn_cred);
- if (!error) {
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (!gotvp) {
- if (newvp) {
- vput(newvp);
- newvp = NULL;
- }
- error = nfs_lookitup(dvp, cnp->cn_nameptr,
- cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- }
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- m_freem(mrep);
-nfsmout:
- if (error) {
- if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
- fmode &= ~O_EXCL;
- goto again;
- }
- if (newvp)
- vput(newvp);
- } else if (v3 && (fmode & O_EXCL)) {
- /*
- * We are normally called with only a partially initialized
- * VAP. Since the NFSv3 spec says that server may use the
- * file attributes to store the verifier, the spec requires
- * us to do a SETATTR RPC. FreeBSD servers store the verifier
- * in atime, but we can't really assume that all servers will
- * so we ensure that our SETATTR sets both atime and mtime.
- */
- if (vap->va_mtime.tv_sec == VNOVAL)
- vfs_timestamp(&vap->va_mtime);
- if (vap->va_atime.tv_sec == VNOVAL)
- vap->va_atime = vap->va_mtime;
- error = nfs_setattrrpc(newvp, vap, cnp->cn_cred);
- if (error)
- vput(newvp);
- }
- if (!error) {
- *ap->a_vpp = newvp;
- }
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- return (error);
-}
-
-/*
- * nfs file remove call
- * To try and make nfs semantics closer to ufs semantics, a file that has
- * other processes using the vnode is renamed instead of removed and then
- * removed later on the last close.
- * - If v_usecount > 1
- * If a rename is not already in the works
- * call nfs_sillyrename() to set it up
- * else
- * do the remove rpc
- */
-static int
-nfs_remove(struct vop_remove_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- struct nfsnode *np = VTONFS(vp);
- int error = 0;
- struct vattr vattr;
-
- KASSERT((cnp->cn_flags & HASBUF) != 0, ("nfs_remove: no name"));
- KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount"));
- if (vp->v_type == VDIR)
- error = EPERM;
- else if (vrefcnt(vp) == 1 || (np->n_sillyrename &&
- !VOP_GETATTR(vp, &vattr, cnp->cn_cred) && vattr.va_nlink > 1)) {
- /*
- * Purge the name cache so that the chance of a lookup for
- * the name succeeding while the remove is in progress is
- * minimized. Without node locking it can still happen, such
- * that an I/O op returns ESTALE, but since you get this if
- * another host removes the file..
- */
- cache_purge(vp);
- /*
- * throw away biocache buffers, mainly to avoid
- * unnecessary delayed writes later.
- */
- error = nfs_vinvalbuf(vp, 0, cnp->cn_thread, 1);
- /* Do the rpc */
- if (error != EINTR && error != EIO)
- error = nfs_removerpc(dvp, cnp->cn_nameptr,
- cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
- /*
- * Kludge City: If the first reply to the remove rpc is lost..
- * the reply to the retransmitted request will be ENOENT
- * since the file was in fact removed
- * Therefore, we cheat and return success.
- */
- if (error == ENOENT)
- error = 0;
- } else if (!np->n_sillyrename)
- error = nfs_sillyrename(dvp, vp, cnp);
- mtx_lock(&np->n_mtx);
- np->n_attrstamp = 0;
- mtx_unlock(&np->n_mtx);
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- return (error);
-}
-
-/*
- * nfs file remove rpc called from nfs_inactive
- */
-int
-nfs_removeit(struct sillyrename *sp)
-{
- /*
- * Make sure that the directory vnode is still valid.
- * XXX we should lock sp->s_dvp here.
- */
- if (sp->s_dvp->v_type == VBAD)
- return (0);
- return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
- NULL));
-}
-
-/*
- * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
- */
-static int
-nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
- struct ucred *cred, struct thread *td)
-{
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_REMOVE]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen),
- M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- m_freem(mrep);
-nfsmout:
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- return (error);
-}
-
-/*
- * nfs file rename call
- */
-static int
-nfs_rename(struct vop_rename_args *ap)
-{
- struct vnode *fvp = ap->a_fvp;
- struct vnode *tvp = ap->a_tvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct componentname *tcnp = ap->a_tcnp;
- struct componentname *fcnp = ap->a_fcnp;
- int error;
-
- KASSERT((tcnp->cn_flags & HASBUF) != 0 &&
- (fcnp->cn_flags & HASBUF) != 0, ("nfs_rename: no name"));
- /* Check for cross-device rename */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- error = EXDEV;
- goto out;
- }
-
- if (fvp == tvp) {
- nfs_printf("nfs_rename: fvp == tvp (can't happen)\n");
- error = 0;
- goto out;
- }
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
- goto out;
-
- /*
- * We have to flush B_DELWRI data prior to renaming
- * the file. If we don't, the delayed-write buffers
- * can be flushed out later after the file has gone stale
- * under NFSV3. NFSV2 does not have this problem because
- * ( as far as I can tell ) it flushes dirty buffers more
- * often.
- *
- * Skip the rename operation if the fsync fails, this can happen
- * due to the server's volume being full, when we pushed out data
- * that was written back to our cache earlier. Not checking for
- * this condition can result in potential (silent) data loss.
- */
- error = VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_thread);
- VOP_UNLOCK(fvp, 0);
- if (!error && tvp)
- error = VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_thread);
- if (error)
- goto out;
-
- /*
- * If the tvp exists and is in use, sillyrename it before doing the
- * rename of the new file over it.
- * XXX Can't sillyrename a directory.
- */
- if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename &&
- tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
- vput(tvp);
- tvp = NULL;
- }
-
- error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
- tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
- tcnp->cn_thread);
-
- if (fvp->v_type == VDIR) {
- if (tvp != NULL && tvp->v_type == VDIR)
- cache_purge(tdvp);
- cache_purge(fdvp);
- }
-
-out:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- /*
- * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
- */
- if (error == ENOENT)
- error = 0;
- return (error);
-}
-
-/*
- * nfs file rename rpc called from nfs_remove() above
- */
-static int
-nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
- struct sillyrename *sp)
-{
-
- return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, sdvp,
- sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
-}
-
-/*
- * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
- */
-static int
-nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
- struct vnode *tdvp, const char *tnameptr, int tnamelen, struct ucred *cred,
- struct thread *td)
-{
- caddr_t bpos, dpos;
- int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(fdvp);
-
- nfsstats.rpccnt[NFSPROC_RENAME]++;
- mreq = m_get2((NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
- nfsm_rndup(tnamelen), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(fdvp, v3);
- nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
- nfsm_fhtom(tdvp, v3);
- nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
- nfsm_request(fdvp, NFSPROC_RENAME, td, cred);
- if (v3) {
- nfsm_wcc_data(fdvp, fwccflag);
- nfsm_wcc_data(tdvp, twccflag);
- }
- m_freem(mrep);
-nfsmout:
- mtx_lock(&(VTONFS(fdvp))->n_mtx);
- VTONFS(fdvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(fdvp))->n_mtx);
- mtx_lock(&(VTONFS(tdvp))->n_mtx);
- VTONFS(tdvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(tdvp))->n_mtx);
- if (!fwccflag) {
- VTONFS(fdvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp);
- }
- if (!twccflag) {
- VTONFS(tdvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
- }
- return (error);
-}
-
-/*
- * nfs hard link create call
- */
-static int
-nfs_link(struct vop_link_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *tdvp = ap->a_tdvp;
- struct componentname *cnp = ap->a_cnp;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3;
-
- if (vp->v_mount != tdvp->v_mount) {
- return (EXDEV);
- }
-
- /*
- * Push all writes to the server, so that the attribute cache
- * doesn't get "out of sync" with the server.
- * XXX There should be a better way!
- */
- VOP_FSYNC(vp, MNT_WAIT, cnp->cn_thread);
-
- v3 = NFS_ISV3(vp);
- nfsstats.rpccnt[NFSPROC_LINK]++;
- mreq = m_get2(NFSX_FH(v3)*2 + NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- nfsm_fhtom(tdvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- nfsm_request(vp, NFSPROC_LINK, cnp->cn_thread, cnp->cn_cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- nfsm_wcc_data(tdvp, wccflag);
- }
- m_freem(mrep);
-nfsmout:
- mtx_lock(&(VTONFS(tdvp))->n_mtx);
- VTONFS(tdvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(tdvp))->n_mtx);
- if (!attrflag) {
- VTONFS(vp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
- }
- if (!wccflag) {
- VTONFS(tdvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
- }
- return (error);
-}
-
-/*
- * nfs symbolic link create call
- */
-static int
-nfs_symlink(struct vop_symlink_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vattr *vap = ap->a_vap;
- struct componentname *cnp = ap->a_cnp;
- struct nfsv2_sattr *sp;
- caddr_t bpos, dpos;
- int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct vnode *newvp = NULL;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_SYMLINK]++;
- slen = strlen(ap->a_target);
- mreq = m_get2(NFSX_FH(v3) + 2*NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3),
- M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_v3attrbuild(vap, FALSE);
- }
- nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
- if (!v3) {
- sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = nfs_xdrneg1;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
-
- /*
- * Issue the NFS request and get the rpc response.
- *
- * Only NFSv3 responses returning an error of 0 actually return
- * a file handle that can be converted into newvp without having
- * to do an extra lookup rpc.
- */
- nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_thread, cnp->cn_cred);
- if (v3) {
- if (error == 0)
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- nfsm_wcc_data(dvp, wccflag);
- }
-
- /*
- * out code jumps -> here, mrep is also freed.
- */
-
- m_freem(mrep);
-nfsmout:
-
- /*
- * If we do not have an error and we could not extract the newvp from
- * the response due to the request being NFSv2, we have to do a
- * lookup in order to obtain a newvp to return.
- */
- if (error == 0 && newvp == NULL) {
- struct nfsnode *np = NULL;
-
- error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
- cnp->cn_cred, cnp->cn_thread, &np);
- if (!error)
- newvp = NFSTOV(np);
- }
- if (error) {
- if (newvp)
- vput(newvp);
- } else {
- *ap->a_vpp = newvp;
- }
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- return (error);
-}
-
-/*
- * nfs make dir call
- */
-static int
-nfs_mkdir(struct vop_mkdir_args *ap)
-{
- struct vnode *dvp = ap->a_dvp;
- struct vattr *vap = ap->a_vap;
- struct componentname *cnp = ap->a_cnp;
- struct nfsv2_sattr *sp;
- int len;
- struct nfsnode *np = NULL;
- struct vnode *newvp = NULL;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- int gotvp = 0;
- struct mbuf *mreq, *mrep, *md, *mb;
- struct vattr vattr;
- int v3 = NFS_ISV3(dvp);
-
- if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0)
- return (error);
- len = cnp->cn_namelen;
- nfsstats.rpccnt[NFSPROC_MKDIR]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) +
- NFSX_SATTR(v3), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
- if (v3) {
- nfsm_v3attrbuild(vap, FALSE);
- } else {
- sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
- sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
- sp->sa_uid = nfs_xdrneg1;
- sp->sa_gid = nfs_xdrneg1;
- sp->sa_size = nfs_xdrneg1;
- txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
- txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
- }
- nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_thread, cnp->cn_cred);
- if (!error)
- nfsm_mtofh(dvp, newvp, v3, gotvp);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- m_freem(mrep);
-nfsmout:
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- if (error == 0 && newvp == NULL) {
- error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
- cnp->cn_thread, &np);
- if (!error) {
- newvp = NFSTOV(np);
- if (newvp->v_type != VDIR)
- error = EEXIST;
- }
- }
- if (error) {
- if (newvp)
- vput(newvp);
- } else
- *ap->a_vpp = newvp;
- return (error);
-}
-
-/*
- * nfs remove directory call
- */
-static int
-nfs_rmdir(struct vop_rmdir_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb;
- int v3 = NFS_ISV3(dvp);
-
- if (dvp == vp)
- return (EINVAL);
- nfsstats.rpccnt[NFSPROC_RMDIR]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED +
- nfsm_rndup(cnp->cn_namelen), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_thread, cnp->cn_cred);
- if (v3)
- nfsm_wcc_data(dvp, wccflag);
- m_freem(mrep);
-nfsmout:
- mtx_lock(&(VTONFS(dvp))->n_mtx);
- VTONFS(dvp)->n_flag |= NMODIFIED;
- mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag) {
- VTONFS(dvp)->n_attrstamp = 0;
- KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
- }
- cache_purge(dvp);
- cache_purge(vp);
- /*
- * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
- */
- if (error == ENOENT)
- error = 0;
- return (error);
-}
-
-/*
- * nfs readdir call
- */
-static int
-nfs_readdir(struct vop_readdir_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct uio *uio = ap->a_uio;
- int tresid, error = 0;
- struct vattr vattr;
-
- if (vp->v_type != VDIR)
- return(EPERM);
-
- /*
- * First, check for hit on the EOF offset cache
- */
- if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
- (np->n_flag & NMODIFIED) == 0) {
- if (VOP_GETATTR(vp, &vattr, ap->a_cred) == 0) {
- mtx_lock(&np->n_mtx);
- if (!NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
- mtx_unlock(&np->n_mtx);
- nfsstats.direofcache_hits++;
- goto out;
- } else
- mtx_unlock(&np->n_mtx);
- }
- }
-
- /*
- * Call nfs_bioread() to do the real work.
- */
- tresid = uio->uio_resid;
- error = nfs_bioread(vp, uio, 0, ap->a_cred);
-
- if (!error && uio->uio_resid == tresid) {
- nfsstats.direofcache_misses++;
- }
-out:
- return (error);
-}
-
-/*
- * Readdir rpc call.
- * Called from below the buffer cache by nfs_doio().
- */
-int
-nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
-{
- int len, left;
- struct dirent *dp = NULL;
- u_int32_t *tl;
- caddr_t cp;
- nfsuint64 *cookiep;
- caddr_t bpos, dpos;
- struct mbuf *mreq, *mrep, *md, *mb;
- nfsuint64 cookie;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct nfsnode *dnp = VTONFS(vp);
- u_quad_t fileno;
- int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
- int attrflag;
- int v3 = NFS_ISV3(vp);
-
- KASSERT(uiop->uio_iovcnt == 1 &&
- (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 &&
- (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
- ("nfs readdirrpc bad uio"));
-
- /*
- * If there is no cookie, assume directory was stale.
- */
- nfs_dircookie_lock(dnp);
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
- if (cookiep) {
- cookie = *cookiep;
- nfs_dircookie_unlock(dnp);
- } else {
- nfs_dircookie_unlock(dnp);
- return (NFSERR_BAD_COOKIE);
- }
-
- /*
- * Loop around doing readdir rpc's of size nm_readdirsize
- * truncated to a multiple of DIRBLKSIZ.
- * The stopping criteria is EOF or buffer full.
- */
- while (more_dirs && bigenough) {
- nfsstats.rpccnt[NFSPROC_READDIR]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_READDIR(v3), M_WAITOK,
- MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, v3);
- if (v3) {
- tl = nfsm_build(u_int32_t *, 5 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- *tl++ = cookie.nfsuquad[1];
- mtx_lock(&dnp->n_mtx);
- *tl++ = dnp->n_cookieverf.nfsuquad[0];
- *tl++ = dnp->n_cookieverf.nfsuquad[1];
- mtx_unlock(&dnp->n_mtx);
- } else {
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- }
- *tl = txdr_unsigned(nmp->nm_readdirsize);
- nfsm_request(vp, NFSPROC_READDIR, uiop->uio_td, cred);
- if (v3) {
- nfsm_postop_attr(vp, attrflag);
- if (!error) {
- tl = nfsm_dissect(u_int32_t *,
- 2 * NFSX_UNSIGNED);
- mtx_lock(&dnp->n_mtx);
- dnp->n_cookieverf.nfsuquad[0] = *tl++;
- dnp->n_cookieverf.nfsuquad[1] = *tl;
- mtx_unlock(&dnp->n_mtx);
- } else {
- m_freem(mrep);
- goto nfsmout;
- }
- }
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- more_dirs = fxdr_unsigned(int, *tl);
-
- /* loop thru the dir entries, doctoring them to 4bsd form */
- while (more_dirs && bigenough) {
- if (v3) {
- tl = nfsm_dissect(u_int32_t *,
- 3 * NFSX_UNSIGNED);
- fileno = fxdr_hyper(tl);
- len = fxdr_unsigned(int, *(tl + 2));
- } else {
- tl = nfsm_dissect(u_int32_t *,
- 2 * NFSX_UNSIGNED);
- fileno = fxdr_unsigned(u_quad_t, *tl++);
- len = fxdr_unsigned(int, *tl);
- }
- if (len <= 0 || len > NFS_MAXNAMLEN) {
- error = EBADRPC;
- m_freem(mrep);
- goto nfsmout;
- }
- tlen = nfsm_rndup(len);
- if (tlen == len)
- tlen += 4; /* To ensure null termination */
- left = DIRBLKSIZ - blksiz;
- if ((tlen + DIRHDSIZ) > 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_offset += left;
- uiop->uio_resid -= left;
- blksiz = 0;
- }
- if ((tlen + DIRHDSIZ) > uiop->uio_resid)
- bigenough = 0;
- if (bigenough) {
- dp = (struct dirent *)uiop->uio_iov->iov_base;
- dp->d_fileno = (int)fileno;
- dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ;
- dp->d_type = DT_UNKNOWN;
- blksiz += dp->d_reclen;
- if (blksiz == DIRBLKSIZ)
- blksiz = 0;
- uiop->uio_offset += DIRHDSIZ;
- uiop->uio_resid -= DIRHDSIZ;
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
- uiop->uio_iov->iov_len -= DIRHDSIZ;
- nfsm_mtouio(uiop, len);
- cp = uiop->uio_iov->iov_base;
- tlen -= len;
- *cp = '\0'; /* null terminate */
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + tlen;
- uiop->uio_iov->iov_len -= tlen;
- uiop->uio_offset += tlen;
- uiop->uio_resid -= tlen;
- } else
- nfsm_adv(nfsm_rndup(len));
- if (v3) {
- tl = nfsm_dissect(u_int32_t *,
- 3 * NFSX_UNSIGNED);
- } else {
- tl = nfsm_dissect(u_int32_t *,
- 2 * NFSX_UNSIGNED);
- }
- if (bigenough) {
- cookie.nfsuquad[0] = *tl++;
- if (v3)
- cookie.nfsuquad[1] = *tl++;
- } else if (v3)
- tl += 2;
- else
- tl++;
- more_dirs = fxdr_unsigned(int, *tl);
- }
- /*
- * If at end of rpc data, get the eof boolean
- */
- if (!more_dirs) {
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- more_dirs = (fxdr_unsigned(int, *tl) == 0);
- }
- m_freem(mrep);
- }
- /*
- * 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;
- dp->d_reclen += left;
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + left;
- uiop->uio_iov->iov_len -= left;
- uiop->uio_offset += left;
- uiop->uio_resid -= left;
- }
-
- /*
- * We are now either at the end of the directory or have filled the
- * block.
- */
- if (bigenough)
- dnp->n_direofoffset = uiop->uio_offset;
- else {
- if (uiop->uio_resid > 0)
- nfs_printf("EEK! readdirrpc resid > 0\n");
- nfs_dircookie_lock(dnp);
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
- *cookiep = cookie;
- nfs_dircookie_unlock(dnp);
- }
-nfsmout:
- return (error);
-}
-
-/*
- * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
- */
-int
-nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
-{
- int len, left;
- struct dirent *dp;
- u_int32_t *tl;
- caddr_t cp;
- struct vnode *newvp;
- nfsuint64 *cookiep;
- caddr_t bpos, dpos, dpossav1, dpossav2;
- struct mbuf *mreq, *mrep, *md, *mb, *mdsav1, *mdsav2;
- struct nameidata nami, *ndp = &nami;
- struct componentname *cnp = &ndp->ni_cnd;
- nfsuint64 cookie;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- struct nfsnode *dnp = VTONFS(vp), *np;
- struct vattr vattr, dvattr;
- nfsfh_t *fhp;
- u_quad_t fileno;
- int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
- int attrflag, dattrflag, fhsize;
-
-#ifndef nolint
- dp = NULL;
-#endif
- KASSERT(uiop->uio_iovcnt == 1 &&
- (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 &&
- (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
- ("nfs readdirplusrpc bad uio"));
- ndp->ni_dvp = vp;
- newvp = NULLVP;
-
- /*
- * If there is no cookie, assume directory was stale.
- */
- nfs_dircookie_lock(dnp);
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
- if (cookiep) {
- cookie = *cookiep;
- nfs_dircookie_unlock(dnp);
- } else {
- nfs_dircookie_unlock(dnp);
- return (NFSERR_BAD_COOKIE);
- }
- /*
- * Loop around doing readdir rpc's of size nm_readdirsize
- * truncated to a multiple of DIRBLKSIZ.
- * The stopping criteria is EOF or buffer full.
- */
- while (more_dirs && bigenough) {
- nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
- mreq = m_get2(NFSX_FH(1) + 6 * NFSX_UNSIGNED, M_WAITOK,
- MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, 1);
- tl = nfsm_build(u_int32_t *, 6 * NFSX_UNSIGNED);
- *tl++ = cookie.nfsuquad[0];
- *tl++ = cookie.nfsuquad[1];
- mtx_lock(&dnp->n_mtx);
- *tl++ = dnp->n_cookieverf.nfsuquad[0];
- *tl++ = dnp->n_cookieverf.nfsuquad[1];
- mtx_unlock(&dnp->n_mtx);
- *tl++ = txdr_unsigned(nmp->nm_readdirsize);
- *tl = txdr_unsigned(nmp->nm_rsize);
- nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, cred);
- nfsm_postop_attr_va(vp, dattrflag, &dvattr);
- if (error) {
- m_freem(mrep);
- goto nfsmout;
- }
- tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
- mtx_lock(&dnp->n_mtx);
- dnp->n_cookieverf.nfsuquad[0] = *tl++;
- dnp->n_cookieverf.nfsuquad[1] = *tl++;
- mtx_unlock(&dnp->n_mtx);
- more_dirs = fxdr_unsigned(int, *tl);
-
- /* loop thru the dir entries, doctoring them to 4bsd form */
- while (more_dirs && bigenough) {
- tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
- fileno = fxdr_hyper(tl);
- len = fxdr_unsigned(int, *(tl + 2));
- if (len <= 0 || len > NFS_MAXNAMLEN) {
- error = EBADRPC;
- m_freem(mrep);
- goto nfsmout;
- }
- tlen = nfsm_rndup(len);
- if (tlen == len)
- tlen += 4; /* To ensure null termination*/
- left = DIRBLKSIZ - blksiz;
- if ((tlen + DIRHDSIZ) > 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_offset += left;
- uiop->uio_resid -= left;
- blksiz = 0;
- }
- if ((tlen + DIRHDSIZ) > uiop->uio_resid)
- bigenough = 0;
- if (bigenough) {
- dp = (struct dirent *)uiop->uio_iov->iov_base;
- dp->d_fileno = (int)fileno;
- dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ;
- dp->d_type = DT_UNKNOWN;
- blksiz += dp->d_reclen;
- if (blksiz == DIRBLKSIZ)
- blksiz = 0;
- uiop->uio_offset += DIRHDSIZ;
- uiop->uio_resid -= 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;
- nfsm_mtouio(uiop, len);
- cp = uiop->uio_iov->iov_base;
- tlen -= len;
- *cp = '\0';
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + tlen;
- uiop->uio_iov->iov_len -= tlen;
- uiop->uio_offset += tlen;
- uiop->uio_resid -= tlen;
- } else
- nfsm_adv(nfsm_rndup(len));
- tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
- if (bigenough) {
- cookie.nfsuquad[0] = *tl++;
- cookie.nfsuquad[1] = *tl++;
- } else
- tl += 2;
-
- /*
- * Since the attributes are before the file handle
- * (sigh), we must skip over the attributes and then
- * come back and get them.
- */
- attrflag = fxdr_unsigned(int, *tl);
- if (attrflag) {
- dpossav1 = dpos;
- mdsav1 = md;
- nfsm_adv(NFSX_V3FATTR);
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- doit = fxdr_unsigned(int, *tl);
- /*
- * Skip loading the attrs for "..". There's a
- * race between loading the attrs here and
- * lookups that look for the directory currently
- * being read (in the parent). We try to acquire
- * the exclusive 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.
- *
- * There are other ways of fixing this, one would
- * be to do a trylock on the ".." vnode and skip
- * loading the attrs on ".." if it happens to be
- * locked by another process. But skipping the
- * attrload on ".." seems the easiest option.
- */
- if (strcmp(dp->d_name, "..") == 0) {
- doit = 0;
- /*
- * We've already skipped over the attrs,
- * skip over the filehandle. And store d_type
- * as VDIR.
- */
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- i = fxdr_unsigned(int, *tl);
- nfsm_adv(nfsm_rndup(i));
- dp->d_type = IFTODT(VTTOIF(VDIR));
- }
- if (doit) {
- nfsm_getfh(fhp, fhsize, 1);
- if (NFS_CMPFH(dnp, fhp, fhsize)) {
- VREF(vp);
- newvp = vp;
- np = dnp;
- } else {
- error = nfs_nget(vp->v_mount, fhp,
- fhsize, &np, LK_EXCLUSIVE);
- if (error)
- doit = 0;
- else
- newvp = NFSTOV(np);
- }
- }
- if (doit && bigenough) {
- dpossav2 = dpos;
- dpos = dpossav1;
- mdsav2 = md;
- md = mdsav1;
- nfsm_loadattr(newvp, &vattr);
- dpos = dpossav2;
- md = mdsav2;
- dp->d_type = IFTODT(VTTOIF(vattr.va_type));
- ndp->ni_vp = newvp;
- if (newvp->v_type != VDIR || dattrflag != 0)
- cache_enter_time(ndp->ni_dvp, ndp->ni_vp,
- cnp, &vattr.va_ctime,
- newvp->v_type != VDIR ? NULL :
- &dvattr.va_ctime);
- }
- } else {
- /* Just skip over the file handle */
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- i = fxdr_unsigned(int, *tl);
- if (i) {
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- fhsize = fxdr_unsigned(int, *tl);
- nfsm_adv(nfsm_rndup(fhsize));
- }
- }
- if (newvp != NULLVP) {
- if (newvp == vp)
- vrele(newvp);
- else
- vput(newvp);
- newvp = NULLVP;
- }
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- more_dirs = fxdr_unsigned(int, *tl);
- }
- /*
- * If at end of rpc data, get the eof boolean
- */
- if (!more_dirs) {
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- more_dirs = (fxdr_unsigned(int, *tl) == 0);
- }
- m_freem(mrep);
- }
- /*
- * 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;
- dp->d_reclen += left;
- uiop->uio_iov->iov_base =
- (char *)uiop->uio_iov->iov_base + left;
- uiop->uio_iov->iov_len -= left;
- uiop->uio_offset += left;
- uiop->uio_resid -= left;
- }
-
- /*
- * We are now either at the end of the directory or have filled the
- * block.
- */
- if (bigenough)
- dnp->n_direofoffset = uiop->uio_offset;
- else {
- if (uiop->uio_resid > 0)
- nfs_printf("EEK! readdirplusrpc resid > 0\n");
- nfs_dircookie_lock(dnp);
- cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
- *cookiep = cookie;
- nfs_dircookie_unlock(dnp);
- }
-nfsmout:
- if (newvp != NULLVP) {
- if (newvp == vp)
- vrele(newvp);
- else
- vput(newvp);
- newvp = NULLVP;
- }
- return (error);
-}
-
-/*
- * Silly rename. To make the NFS filesystem that is stateless look a little
- * more like the "ufs" a remove of an active vnode is translated to a rename
- * to a funny looking filename that is removed by nfs_inactive on the
- * nfsnode. There is the potential for another process on a different client
- * to create the same funny name between the nfs_lookitup() fails and the
- * nfs_rename() completes, but...
- */
-static int
-nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
-{
- struct sillyrename *sp;
- struct nfsnode *np;
- int error;
- short pid;
- unsigned int lticks;
-
- cache_purge(dvp);
- np = VTONFS(vp);
- KASSERT(vp->v_type != VDIR, ("nfs: sillyrename dir"));
- sp = malloc(sizeof (struct sillyrename),
- M_NFSREQ, M_WAITOK);
- sp->s_cred = crhold(cnp->cn_cred);
- sp->s_dvp = dvp;
- sp->s_removeit = nfs_removeit;
- VREF(dvp);
-
- /*
- * Fudge together a funny name.
- * Changing the format of the funny name to accomodate more
- * sillynames per directory.
- * The name is now changed to .nfs.<ticks>.<pid>.4, where ticks is
- * CPU ticks since boot.
- */
- pid = cnp->cn_thread->td_proc->p_pid;
- lticks = (unsigned int)ticks;
- for ( ; ; ) {
- sp->s_namlen = sprintf(sp->s_name,
- ".nfs.%08x.%04x4.4", lticks,
- pid);
- if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
- cnp->cn_thread, NULL))
- break;
- lticks++;
- }
- error = nfs_renameit(dvp, cnp, sp);
- if (error)
- goto bad;
- error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
- cnp->cn_thread, &np);
- np->n_sillyrename = sp;
- return (0);
-bad:
- vrele(sp->s_dvp);
- crfree(sp->s_cred);
- free((caddr_t)sp, M_NFSREQ);
- return (error);
-}
-
-/*
- * Look up a file name and optionally either update the file handle or
- * allocate an nfsnode, depending on the value of npp.
- * npp == NULL --> just do the lookup
- * *npp == NULL --> allocate a new nfsnode and make sure attributes are
- * handled too
- * *npp != NULL --> update the file handle in the vnode
- */
-static int
-nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
- struct thread *td, struct nfsnode **npp)
-{
- struct vnode *newvp = NULL;
- struct nfsnode *np, *dnp = VTONFS(dvp);
- caddr_t bpos, dpos;
- int error = 0, fhlen, attrflag;
- struct mbuf *mreq, *mrep, *md, *mb;
- nfsfh_t *nfhp;
- int v3 = NFS_ISV3(dvp);
-
- nfsstats.rpccnt[NFSPROC_LOOKUP]++;
- mreq = m_get2(NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len),
- M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(dvp, v3);
- nfsm_strtom(name, len, NFS_MAXNAMLEN);
- nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
- if (npp && !error) {
- nfsm_getfh(nfhp, fhlen, v3);
- if (*npp) {
- np = *npp;
- if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
- free((caddr_t)np->n_fhp, M_NFSBIGFH);
- np->n_fhp = &np->n_fh;
- } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
- np->n_fhp =(nfsfh_t *)malloc(fhlen, M_NFSBIGFH, M_WAITOK);
- bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
- np->n_fhsize = fhlen;
- newvp = NFSTOV(np);
- } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
- VREF(dvp);
- newvp = dvp;
- } else {
- error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np, LK_EXCLUSIVE);
- if (error) {
- m_freem(mrep);
- return (error);
- }
- newvp = NFSTOV(np);
- }
- if (v3) {
- nfsm_postop_attr(newvp, attrflag);
- if (!attrflag && *npp == NULL) {
- m_freem(mrep);
- if (newvp == dvp)
- vrele(newvp);
- else
- vput(newvp);
- return (ENOENT);
- }
- } else
- nfsm_loadattr(newvp, NULL);
- }
- m_freem(mrep);
-nfsmout:
- if (npp && *npp == NULL) {
- if (error) {
- if (newvp) {
- if (newvp == dvp)
- vrele(newvp);
- else
- vput(newvp);
- }
- } else
- *npp = np;
- }
- return (error);
-}
-
-/*
- * Nfs Version 3 commit rpc
- */
-int
-nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
- struct thread *td)
-{
- u_int32_t *tl;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- caddr_t bpos, dpos;
- int error = 0, wccflag = NFSV3_WCCRATTR;
- struct mbuf *mreq, *mrep, *md, *mb;
-
- mtx_lock(&nmp->nm_mtx);
- if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
- mtx_unlock(&nmp->nm_mtx);
- return (0);
- }
- mtx_unlock(&nmp->nm_mtx);
- nfsstats.rpccnt[NFSPROC_COMMIT]++;
- mreq = m_get2(NFSX_FH(1), M_WAITOK, MT_DATA, 0);
- mb = mreq;
- bpos = mtod(mb, caddr_t);
- nfsm_fhtom(vp, 1);
- tl = nfsm_build(u_int32_t *, 3 * NFSX_UNSIGNED);
- txdr_hyper(offset, tl);
- tl += 2;
- *tl = txdr_unsigned(cnt);
- nfsm_request(vp, NFSPROC_COMMIT, td, cred);
- nfsm_wcc_data(vp, wccflag);
- if (!error) {
- tl = nfsm_dissect(u_int32_t *, NFSX_V3WRITEVERF);
- if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
- NFSX_V3WRITEVERF)) {
- bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
- NFSX_V3WRITEVERF);
- error = NFSERR_STALEWRITEVERF;
- }
- }
- m_freem(mrep);
-nfsmout:
- return (error);
-}
-
-/*
- * Strategy routine.
- * For async requests when nfsiod(s) are running, queue the request by
- * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
- * request.
- */
-static int
-nfs_strategy(struct vop_strategy_args *ap)
-{
- struct buf *bp = ap->a_bp;
- struct ucred *cr;
-
- KASSERT(!(bp->b_flags & B_DONE),
- ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp));
- BUF_ASSERT_HELD(bp);
-
- if (bp->b_iocmd == BIO_READ)
- cr = bp->b_rcred;
- else
- cr = bp->b_wcred;
-
- /*
- * If the op is asynchronous and an i/o daemon is waiting
- * queue the request, wake it up and wait for completion
- * otherwise just do it ourselves.
- */
- if ((bp->b_flags & B_ASYNC) == 0 ||
- nfs_asyncio(VFSTONFS(ap->a_vp->v_mount), bp, NOCRED, curthread))
- (void)nfs_doio(ap->a_vp, bp, cr, curthread);
- return (0);
-}
-
-/*
- * fsync vnode op. Just call nfs_flush() with commit == 1.
- */
-/* ARGSUSED */
-static int
-nfs_fsync(struct vop_fsync_args *ap)
-{
-
- return (nfs_flush(ap->a_vp, ap->a_waitfor, 1));
-}
-
-/*
- * Flush all the blocks associated with a vnode.
- * Walk through the buffer pool and push any dirty pages
- * associated with the vnode.
- */
-static int
-nfs_flush(struct vnode *vp, int waitfor, int commit)
-{
- struct nfsnode *np = VTONFS(vp);
- struct buf *bp;
- int i;
- struct buf *nbp;
- struct nfsmount *nmp = VFSTONFS(vp->v_mount);
- int error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
- int passone = 1;
- u_quad_t off, endoff, toff;
- struct ucred* wcred = NULL;
- struct buf **bvec = NULL;
- struct bufobj *bo;
- struct thread *td = curthread;
-#ifndef NFS_COMMITBVECSIZ
-#define NFS_COMMITBVECSIZ 20
-#endif
- struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
- int bvecsize = 0, bveccount;
-
- if (nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- if (!commit)
- passone = 0;
- bo = &vp->v_bufobj;
- /*
- * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
- * server, but has not been committed to stable storage on the server
- * yet. On the first pass, the byte range is worked out and the commit
- * rpc is done. On the second pass, nfs_writebp() is called to do the
- * job.
- */
-again:
- off = (u_quad_t)-1;
- endoff = 0;
- bvecpos = 0;
- if (NFS_ISV3(vp) && commit) {
- if (bvec != NULL && bvec != bvec_on_stack)
- free(bvec, M_TEMP);
- /*
- * Count up how many buffers waiting for a commit.
- */
- bveccount = 0;
- BO_LOCK(bo);
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (!BUF_ISLOCKED(bp) &&
- (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
- == (B_DELWRI | B_NEEDCOMMIT))
- bveccount++;
- }
- /*
- * Allocate space to remember the list of bufs to commit. It is
- * important to use M_NOWAIT here to avoid a race with nfs_write.
- * If we can't get memory (for whatever reason), we will end up
- * committing the buffers one-by-one in the loop below.
- */
- if (bveccount > NFS_COMMITBVECSIZ) {
- /*
- * Release the vnode interlock to avoid a lock
- * order reversal.
- */
- BO_UNLOCK(bo);
- bvec = (struct buf **)
- malloc(bveccount * sizeof(struct buf *),
- M_TEMP, M_NOWAIT);
- BO_LOCK(bo);
- if (bvec == NULL) {
- bvec = bvec_on_stack;
- bvecsize = NFS_COMMITBVECSIZ;
- } else
- bvecsize = bveccount;
- } else {
- bvec = bvec_on_stack;
- bvecsize = NFS_COMMITBVECSIZ;
- }
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (bvecpos >= bvecsize)
- break;
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
- nbp = TAILQ_NEXT(bp, b_bobufs);
- continue;
- }
- if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) !=
- (B_DELWRI | B_NEEDCOMMIT)) {
- BUF_UNLOCK(bp);
- nbp = TAILQ_NEXT(bp, b_bobufs);
- continue;
- }
- BO_UNLOCK(bo);
- bremfree(bp);
- /*
- * Work out if all buffers are using the same cred
- * so we can deal with them all with one commit.
- *
- * NOTE: we are not clearing B_DONE here, so we have
- * to do it later on in this routine if we intend to
- * initiate I/O on the bp.
- *
- * Note: to avoid loopback deadlocks, we do not
- * assign b_runningbufspace.
- */
- if (wcred == NULL)
- wcred = bp->b_wcred;
- else if (wcred != bp->b_wcred)
- wcred = NOCRED;
- vfs_busy_pages(bp, 1);
-
- BO_LOCK(bo);
- /*
- * bp is protected by being locked, but nbp is not
- * and vfs_busy_pages() may sleep. We have to
- * recalculate nbp.
- */
- nbp = TAILQ_NEXT(bp, b_bobufs);
-
- /*
- * A list of these buffers is kept so that the
- * second loop knows which buffers have actually
- * been committed. This is necessary, since there
- * may be a race between the commit rpc and new
- * uncommitted writes on the file.
- */
- bvec[bvecpos++] = bp;
- toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
- bp->b_dirtyoff;
- if (toff < off)
- off = toff;
- toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
- if (toff > endoff)
- endoff = toff;
- }
- BO_UNLOCK(bo);
- }
- if (bvecpos > 0) {
- /*
- * Commit data on the server, as required.
- * If all bufs are using the same wcred, then use that with
- * one call for all of them, otherwise commit each one
- * separately.
- */
- if (wcred != NOCRED)
- retv = nfs_commit(vp, off, (int)(endoff - off),
- wcred, td);
- else {
- retv = 0;
- for (i = 0; i < bvecpos; i++) {
- off_t off, size;
- bp = bvec[i];
- off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
- bp->b_dirtyoff;
- size = (u_quad_t)(bp->b_dirtyend
- - bp->b_dirtyoff);
- retv = nfs_commit(vp, off, (int)size,
- bp->b_wcred, td);
- if (retv) break;
- }
- }
-
- if (retv == NFSERR_STALEWRITEVERF)
- nfs_clearcommit(vp->v_mount);
-
- /*
- * Now, either mark the blocks I/O done or mark the
- * blocks dirty, depending on whether the commit
- * succeeded.
- */
- for (i = 0; i < bvecpos; i++) {
- bp = bvec[i];
- bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
- if (retv) {
- /*
- * Error, leave B_DELWRI intact
- */
- vfs_unbusy_pages(bp);
- brelse(bp);
- } else {
- /*
- * Success, remove B_DELWRI ( bundirty() ).
- *
- * b_dirtyoff/b_dirtyend seem to be NFS
- * specific. We should probably move that
- * into bundirty(). XXX
- */
- bufobj_wref(bo);
- bp->b_flags |= B_ASYNC;
- bundirty(bp);
- bp->b_flags &= ~B_DONE;
- bp->b_ioflags &= ~BIO_ERROR;
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- bufdone(bp);
- }
- }
- }
-
- /*
- * Start/do any write(s) that are required.
- */
-loop:
- BO_LOCK(bo);
- TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
- if (waitfor != MNT_WAIT || passone)
- continue;
-
- error = BUF_TIMELOCK(bp,
- LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
- BO_LOCKPTR(bo), "nfsfsync", slpflag, slptimeo);
- if (error == 0) {
- BUF_UNLOCK(bp);
- goto loop;
- }
- if (error == ENOLCK) {
- error = 0;
- goto loop;
- }
- if (nfs_sigintr(nmp, td)) {
- error = EINTR;
- goto done;
- }
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- goto loop;
- }
- if ((bp->b_flags & B_DELWRI) == 0)
- panic("nfs_fsync: not dirty");
- if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) {
- BUF_UNLOCK(bp);
- continue;
- }
- BO_UNLOCK(bo);
- bremfree(bp);
- if (passone || !commit)
- bp->b_flags |= B_ASYNC;
- else
- bp->b_flags |= B_ASYNC;
- bwrite(bp);
- if (nfs_sigintr(nmp, td)) {
- error = EINTR;
- goto done;
- }
- goto loop;
- }
- if (passone) {
- passone = 0;
- BO_UNLOCK(bo);
- goto again;
- }
- if (waitfor == MNT_WAIT) {
- while (bo->bo_numoutput) {
- error = bufobj_wwait(bo, slpflag, slptimeo);
- if (error) {
- BO_UNLOCK(bo);
- error = nfs_sigintr(nmp, td);
- if (error)
- goto done;
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- BO_LOCK(bo);
- }
- }
- if (bo->bo_dirty.bv_cnt != 0 && commit) {
- BO_UNLOCK(bo);
- goto loop;
- }
- /*
- * Wait for all the async IO requests to drain
- */
- BO_UNLOCK(bo);
- mtx_lock(&np->n_mtx);
- while (np->n_directio_asyncwr > 0) {
- np->n_flag |= NFSYNCWAIT;
- error = nfs_msleep(td, (caddr_t)&np->n_directio_asyncwr,
- &np->n_mtx, slpflag | (PRIBIO + 1),
- "nfsfsync", 0);
- if (error) {
- if (nfs_sigintr(nmp, td)) {
- mtx_unlock(&np->n_mtx);
- error = EINTR;
- goto done;
- }
- }
- }
- mtx_unlock(&np->n_mtx);
- } else
- BO_UNLOCK(bo);
- mtx_lock(&np->n_mtx);
- if (np->n_flag & NWRITEERR) {
- error = np->n_error;
- np->n_flag &= ~NWRITEERR;
- }
- if (commit && bo->bo_dirty.bv_cnt == 0 &&
- bo->bo_numoutput == 0 && np->n_directio_asyncwr == 0)
- np->n_flag &= ~NMODIFIED;
- mtx_unlock(&np->n_mtx);
-done:
- if (bvec != NULL && bvec != bvec_on_stack)
- free(bvec, M_TEMP);
- return (error);
-}
-
-/*
- * NFS advisory byte-level locks.
- */
-static int
-nfs_advlock(struct vop_advlock_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- u_quad_t size;
- int error;
-
- error = vn_lock(vp, LK_SHARED);
- if (error)
- return (error);
- if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
- size = VTONFS(vp)->n_size;
- VOP_UNLOCK(vp, 0);
- error = lf_advlock(ap, &(vp->v_lockf), size);
- } else {
- if (nfs_advlock_p)
- error = nfs_advlock_p(ap);
- else
- error = ENOLCK;
- }
-
- return (error);
-}
-
-/*
- * NFS advisory byte-level locks.
- */
-static int
-nfs_advlockasync(struct vop_advlockasync_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- u_quad_t size;
- int error;
-
- error = vn_lock(vp, LK_SHARED);
- if (error)
- return (error);
- if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
- size = VTONFS(vp)->n_size;
- VOP_UNLOCK(vp, 0);
- error = lf_advlockasync(ap, &(vp->v_lockf), size);
- } else {
- VOP_UNLOCK(vp, 0);
- error = EOPNOTSUPP;
- }
- return (error);
-}
-
-/*
- * Print out the contents of an nfsnode.
- */
-static int
-nfs_print(struct vop_print_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
-
- nfs_printf("\tfileid %ld fsid 0x%x",
- np->n_vattr.va_fileid, np->n_vattr.va_fsid);
- if (vp->v_type == VFIFO)
- fifo_printinfo(vp);
- printf("\n");
- return (0);
-}
-
-/*
- * This is the "real" nfs::bwrite(struct buf*).
- * We set B_CACHE if this is a VMIO buffer.
- */
-int
-nfs_writebp(struct buf *bp, int force __unused, struct thread *td)
-{
- int s;
- int oldflags = bp->b_flags;
-#if 0
- int retv = 1;
- off_t off;
-#endif
-
- BUF_ASSERT_HELD(bp);
-
- if (bp->b_flags & B_INVAL) {
- brelse(bp);
- return(0);
- }
-
- bp->b_flags |= B_CACHE;
-
- /*
- * Undirty the bp. We will redirty it later if the I/O fails.
- */
-
- s = splbio();
- bundirty(bp);
- bp->b_flags &= ~B_DONE;
- bp->b_ioflags &= ~BIO_ERROR;
- bp->b_iocmd = BIO_WRITE;
-
- bufobj_wref(bp->b_bufobj);
- curthread->td_ru.ru_oublock++;
- splx(s);
-
- /*
- * Note: to avoid loopback deadlocks, we do not
- * assign b_runningbufspace.
- */
- vfs_busy_pages(bp, 1);
-
- BUF_KERNPROC(bp);
- bp->b_iooffset = dbtob(bp->b_blkno);
- bstrategy(bp);
-
- if( (oldflags & B_ASYNC) == 0) {
- int rtval = bufwait(bp);
-
- if (oldflags & B_DELWRI) {
- s = splbio();
- reassignbuf(bp);
- splx(s);
- }
- brelse(bp);
- return (rtval);
- }
-
- return (0);
-}
-
-/*
- * nfs special file access vnode op.
- * Essentially just get vattr and then imitate iaccess() since the device is
- * local to the client.
- */
-static int
-nfsspec_access(struct vop_access_args *ap)
-{
- struct vattr *vap;
- struct ucred *cred = ap->a_cred;
- struct vnode *vp = ap->a_vp;
- accmode_t accmode = ap->a_accmode;
- struct vattr vattr;
- int error;
-
- /*
- * Disallow write attempts on filesystems mounted read-only;
- * unless the file is a socket, fifo, or a block or character
- * device resident on the filesystem.
- */
- if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
- vap = &vattr;
- error = VOP_GETATTR(vp, vap, cred);
- if (error)
- goto out;
- error = vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid,
- accmode, cred, NULL);
-out:
- return error;
-}
-
-/*
- * Read wrapper for fifos.
- */
-static int
-nfsfifo_read(struct vop_read_args *ap)
-{
- struct nfsnode *np = VTONFS(ap->a_vp);
- int error;
-
- /*
- * Set access flag.
- */
- mtx_lock(&np->n_mtx);
- np->n_flag |= NACC;
- vfs_timestamp(&np->n_atim);
- mtx_unlock(&np->n_mtx);
- error = fifo_specops.vop_read(ap);
- return error;
-}
-
-/*
- * Write wrapper for fifos.
- */
-static int
-nfsfifo_write(struct vop_write_args *ap)
-{
- struct nfsnode *np = VTONFS(ap->a_vp);
-
- /*
- * Set update flag.
- */
- mtx_lock(&np->n_mtx);
- np->n_flag |= NUPD;
- vfs_timestamp(&np->n_mtim);
- mtx_unlock(&np->n_mtx);
- return(fifo_specops.vop_write(ap));
-}
-
-/*
- * Close wrapper for fifos.
- *
- * Update the times on the nfsnode then do fifo close.
- */
-static int
-nfsfifo_close(struct vop_close_args *ap)
-{
- struct vnode *vp = ap->a_vp;
- struct nfsnode *np = VTONFS(vp);
- struct vattr vattr;
- struct timespec ts;
-
- mtx_lock(&np->n_mtx);
- if (np->n_flag & (NACC | NUPD)) {
- vfs_timestamp(&ts);
- if (np->n_flag & NACC)
- np->n_atim = ts;
- if (np->n_flag & NUPD)
- np->n_mtim = ts;
- np->n_flag |= NCHG;
- if (vrefcnt(vp) == 1 &&
- (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
- VATTR_NULL(&vattr);
- if (np->n_flag & NACC)
- vattr.va_atime = np->n_atim;
- if (np->n_flag & NUPD)
- vattr.va_mtime = np->n_mtim;
- mtx_unlock(&np->n_mtx);
- (void)VOP_SETATTR(vp, &vattr, ap->a_cred);
- goto out;
- }
- }
- mtx_unlock(&np->n_mtx);
-out:
- return (fifo_specops.vop_close(ap));
-}
-
-/*
- * Just call nfs_writebp() with the force argument set to 1.
- *
- * NOTE: B_DONE may or may not be set in a_bp on call.
- */
-static int
-nfs_bwrite(struct buf *bp)
-{
-
- return (nfs_writebp(bp, 1, curthread));
-}
-
-struct buf_ops buf_ops_nfs = {
- .bop_name = "buf_ops_nfs",
- .bop_write = nfs_bwrite,
- .bop_strategy = bufstrategy,
- .bop_sync = bufsync,
- .bop_bdflush = bufbdflush,
-};
diff --git a/sys/nfsserver/nfs_fha_old.c b/sys/nfsserver/nfs_fha_old.c
deleted file mode 100644
index a928278..0000000
--- a/sys/nfsserver/nfs_fha_old.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*-
- * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
- * Copyright (c) 2013 Spectra Logic Corporation
- *
- * 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>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mbuf.h>
-#include <sys/sysctl.h>
-
-#include <rpc/rpc.h>
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs_fha.h>
-#include <nfsserver/nfs.h>
-#include <nfsserver/nfsm_subs.h>
-#include <nfsserver/nfs_fha_old.h>
-
-static void fhaold_init(void *foo);
-static void fhaold_uninit(void *foo);
-rpcproc_t fhaold_get_procnum(rpcproc_t procnum);
-int fhaold_realign(struct mbuf **mb, int malloc_flags);
-int fhaold_get_fh(uint64_t *fh, int v3, struct mbuf **md, caddr_t *dpos);
-int fhaold_is_read(rpcproc_t procnum);
-int fhaold_is_write(rpcproc_t procnum);
-int fhaold_get_offset(struct mbuf **md, caddr_t *dpos, int v3,
- struct fha_info *info);
-int fhaold_no_offset(rpcproc_t procnum);
-void fhaold_set_locktype(rpcproc_t procnum, struct fha_info *info);
-static int fheold_stats_sysctl(SYSCTL_HANDLER_ARGS);
-
-static struct fha_params fhaold_softc;
-
-SYSCTL_DECL(_vfs_nfsrv);
-
-extern SVCPOOL *nfsrv_pool;
-
-SYSINIT(nfs_fhaold, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhaold_init, NULL);
-SYSUNINIT(nfs_fhaold, SI_SUB_ROOT_CONF, SI_ORDER_ANY, fhaold_uninit, NULL);
-
-static void
-fhaold_init(void *foo)
-{
- struct fha_params *softc;
-
- softc = &fhaold_softc;
-
- bzero(softc, sizeof(*softc));
-
- /*
- * Setup the callbacks for this FHA personality.
- */
- softc->callbacks.get_procnum = fhaold_get_procnum;
- softc->callbacks.realign = fhaold_realign;
- softc->callbacks.get_fh = fhaold_get_fh;
- softc->callbacks.is_read = fhaold_is_read;
- softc->callbacks.is_write = fhaold_is_write;
- softc->callbacks.get_offset = fhaold_get_offset;
- softc->callbacks.no_offset = fhaold_no_offset;
- softc->callbacks.set_locktype = fhaold_set_locktype;
- softc->callbacks.fhe_stats_sysctl = fheold_stats_sysctl;
-
- snprintf(softc->server_name, sizeof(softc->server_name),
- FHAOLD_SERVER_NAME);
-
- softc->pool = &nfsrv_pool;
-
- /*
- * Initialize the sysctl context list for the fha module.
- */
- sysctl_ctx_init(&softc->sysctl_ctx);
- softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
- SYSCTL_STATIC_CHILDREN(_vfs_nfsrv), OID_AUTO, "fha", CTLFLAG_RD,
- 0, "fha node");
- if (softc->sysctl_tree == NULL) {
- printf("%s: unable to allocate sysctl tree\n", __func__);
- return;
- }
- fha_init(softc);
-}
-
-static void
-fhaold_uninit(void *foo)
-{
- struct fha_params *softc;
-
- softc = &fhaold_softc;
-
- fha_uninit(softc);
-}
-
-
-rpcproc_t
-fhaold_get_procnum(rpcproc_t procnum)
-{
- if (procnum > NFSV2PROC_STATFS)
- return (-1);
-
- return (nfsrv_nfsv3_procid[procnum]);
-}
-
-int
-fhaold_realign(struct mbuf **mb, int malloc_flags)
-{
- return (nfs_realign(mb, malloc_flags));
-}
-
-int
-fhaold_get_fh(uint64_t *fh, int v3, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
- uint8_t *buf;
- uint64_t t;
- int fhlen, i;
-
- if (v3) {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- fhlen = fxdr_unsigned(int, *tl);
- if (fhlen != 0 && fhlen != NFSX_V3FH)
- return EBADRPC;
- } else {
- fhlen = NFSX_V2FH;
- }
- t = 0;
- if (fhlen != 0) {
- buf = nfsm_dissect_xx_nonblock(fhlen, md, dpos);
- if (buf == NULL)
- return EBADRPC;
- for (i = 0; i < fhlen; i++)
- t ^= ((uint64_t)buf[i] << (i & 7) * 8);
- }
- *fh = t;
- return 0;
-}
-
-int
-fhaold_is_read(rpcproc_t procnum)
-{
- if (procnum == NFSPROC_READ)
- return (1);
- else
- return (0);
-}
-
-int
-fhaold_is_write(rpcproc_t procnum)
-{
- if (procnum == NFSPROC_WRITE)
- return (1);
- else
- return (0);
-}
-
-int
-fhaold_get_offset(struct mbuf **md, caddr_t *dpos, int v3,
- struct fha_info *info)
-{
- uint32_t *tl;
-
- if (v3) {
- tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- goto out;
- info->offset = fxdr_hyper(tl);
- } else {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- goto out;
- info->offset = fxdr_unsigned(uint32_t, *tl);
- }
-
- return (0);
-out:
- return (-1);
-}
-
-int
-fhaold_no_offset(rpcproc_t procnum)
-{
- if (procnum == NFSPROC_FSSTAT ||
- procnum == NFSPROC_FSINFO ||
- procnum == NFSPROC_PATHCONF ||
- procnum == NFSPROC_NOOP ||
- procnum == NFSPROC_NULL)
- return (1);
- else
- return (0);
-}
-
-void
-fhaold_set_locktype(rpcproc_t procnum, struct fha_info *info)
-{
- switch (procnum) {
- case NFSPROC_NULL:
- case NFSPROC_GETATTR:
- case NFSPROC_LOOKUP:
- case NFSPROC_ACCESS:
- case NFSPROC_READLINK:
- case NFSPROC_READ:
- case NFSPROC_READDIR:
- case NFSPROC_READDIRPLUS:
- case NFSPROC_WRITE:
- info->locktype = LK_SHARED;
- break;
- case NFSPROC_SETATTR:
- case NFSPROC_CREATE:
- case NFSPROC_MKDIR:
- case NFSPROC_SYMLINK:
- case NFSPROC_MKNOD:
- case NFSPROC_REMOVE:
- case NFSPROC_RMDIR:
- case NFSPROC_RENAME:
- case NFSPROC_LINK:
- case NFSPROC_FSSTAT:
- case NFSPROC_FSINFO:
- case NFSPROC_PATHCONF:
- case NFSPROC_COMMIT:
- case NFSPROC_NOOP:
- info->locktype = LK_EXCLUSIVE;
- break;
- }
-}
-
-static int
-fheold_stats_sysctl(SYSCTL_HANDLER_ARGS)
-{
- return (fhe_stats_sysctl(oidp, arg1, arg2, req, &fhaold_softc));
-}
-
-SVCTHREAD *
-fhaold_assign(SVCTHREAD *this_thread, struct svc_req *req)
-{
- return (fha_assign(this_thread, req, &fhaold_softc));
-}
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
deleted file mode 100644
index 32fd3f5..0000000
--- a/sys/nfsserver/nfs_serv.c
+++ /dev/null
@@ -1,3767 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * nfs version 2 and 3 server calls to vnode ops
- * - these routines generally have 3 phases
- * 1 - break down and validate rpc request in mbuf list
- * 2 - do the vnode ops for the request
- * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
- * 3 - build the rpc reply in an mbuf list
- * nb:
- * - do not mix the phases, since the nfsm_?? macros can return failures
- * on a bad rpc or similar and do not do any vrele() or vput()'s
- *
- * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
- * error number iff error != 0 whereas
- * returning an error from the server function implies a fatal error
- * such as a badly constructed rpc request that should be dropped without
- * a reply.
- * For nfsm_reply(), the case where error == EBADRPC is treated
- * specially; after constructing a reply, it does an immediate
- * `goto nfsmout' to avoid getting any V3 post-op status appended.
- *
- * Other notes:
- * Warning: always pay careful attention to resource cleanup on return
- * and note that nfsm_*() macros can terminate a procedure on certain
- * errors.
- *
- * lookup() and namei()
- * may return garbage in various structural fields/return elements
- * if an error is returned, and may garbage up nd.ni_dvp even if no
- * error is returned and you did not request LOCKPARENT or WANTPARENT.
- *
- * We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
- * buffer has been freed or not.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/namei.h>
-#include <sys/unistd.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/priv.h>
-#include <sys/dirent.h>
-#include <sys/stat.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/rwlock.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfsserver/nfsm_subs.h>
-
-FEATURE(nfsserver, "NFS server");
-
-#ifdef NFSRV_DEBUG
-#define nfsdbprintf(info) printf info
-#else
-#define nfsdbprintf(info)
-#endif
-
-#define MAX_COMMIT_COUNT (1024 * 1024)
-
-#define MAX_REORDERED_RPC 16
-#define NUM_HEURISTIC 1031
-#define NHUSE_INIT 64
-#define NHUSE_INC 16
-#define NHUSE_MAX 2048
-
-static struct nfsheur {
- struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
- off_t nh_nextoff; /* next offset for sequential detection */
- int nh_use; /* use count for selection */
- int nh_seqcount; /* heuristic */
-} nfsheur[NUM_HEURISTIC];
-
-/* Global vars */
-
-int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
-int nfsrvw_procrastinate_v3 = 0;
-
-static struct timeval nfsver = { 0 };
-
-SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
-
-static int nfs_async;
-static int nfs_commit_blks;
-static int nfs_commit_miss;
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
- "Tell client that writes were synced even though they were not");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0,
- "Number of completed commits");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
-
-struct nfsrvstats nfsrvstats;
-SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
- &nfsrvstats, nfsrvstats, "S,nfsrvstats");
-
-static int nfsrv_access(struct vnode *, accmode_t, struct ucred *,
- int, int);
-
-/*
- * Clear nameidata fields that are tested in nsfmout cleanup code prior
- * to using first nfsm macro (that might jump to the cleanup code).
- */
-
-static __inline void
-ndclear(struct nameidata *nd)
-{
-
- nd->ni_cnd.cn_flags = 0;
- nd->ni_vp = NULL;
- nd->ni_dvp = NULL;
- nd->ni_startdir = NULL;
- nd->ni_strictrelative = 0;
-}
-
-/*
- * Heuristic to detect sequential operation.
- */
-static struct nfsheur *
-nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp)
-{
- struct nfsheur *nh;
- int hi, try;
-
- /* Locate best candidate. */
- try = 32;
- hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
- nh = &nfsheur[hi];
- while (try--) {
- if (nfsheur[hi].nh_vp == vp) {
- nh = &nfsheur[hi];
- break;
- }
- if (nfsheur[hi].nh_use > 0)
- --nfsheur[hi].nh_use;
- hi = (hi + 1) % NUM_HEURISTIC;
- if (nfsheur[hi].nh_use < nh->nh_use)
- nh = &nfsheur[hi];
- }
-
- /* Initialize hint if this is a new file. */
- if (nh->nh_vp != vp) {
- nh->nh_vp = vp;
- nh->nh_nextoff = uio->uio_offset;
- nh->nh_use = NHUSE_INIT;
- if (uio->uio_offset == 0)
- nh->nh_seqcount = 4;
- else
- nh->nh_seqcount = 1;
- }
-
- /* Calculate heuristic. */
- if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) ||
- uio->uio_offset == nh->nh_nextoff) {
- /* See comments in vfs_vnops.c:sequential_heuristic(). */
- nh->nh_seqcount += howmany(uio->uio_resid, 16384);
- if (nh->nh_seqcount > IO_SEQMAX)
- nh->nh_seqcount = IO_SEQMAX;
- } else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC *
- imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) {
- /* Probably a reordered RPC, leave seqcount alone. */
- } else if (nh->nh_seqcount > 1) {
- nh->nh_seqcount /= 2;
- } else {
- nh->nh_seqcount = 0;
- }
- nh->nh_use += NHUSE_INC;
- if (nh->nh_use > NHUSE_MAX)
- nh->nh_use = NHUSE_MAX;
- return (nh);
-}
-
-/*
- * nfs v3 access service
- */
-int
-nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, rdonly, getret;
- struct mbuf *mb, *mreq;
- struct vattr vattr, *vap = &vattr;
- u_long testmode, nfsmode;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (!v3)
- panic("nfsrv3_access: v3 proc called on a v2 connection");
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(1, NULL);
- error = 0;
- goto nfsmout;
- }
- nfsmode = fxdr_unsigned(u_int32_t, *tl);
- if ((nfsmode & NFSV3ACCESS_READ) &&
- nfsrv_access(vp, VREAD, cred, rdonly, 0))
- nfsmode &= ~NFSV3ACCESS_READ;
- if (vp->v_type == VDIR)
- testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
- NFSV3ACCESS_DELETE);
- else
- testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
- if ((nfsmode & testmode) &&
- nfsrv_access(vp, VWRITE, cred, rdonly, 0))
- nfsmode &= ~testmode;
- if (vp->v_type == VDIR)
- testmode = NFSV3ACCESS_LOOKUP;
- else
- testmode = NFSV3ACCESS_EXECUTE;
- if ((nfsmode & testmode) &&
- nfsrv_access(vp, VEXEC, cred, rdonly, 0))
- nfsmode &= ~testmode;
- getret = VOP_GETATTR(vp, vap, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, vap);
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(nfsmode);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs getattr service
- */
-int
-nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nfs_fattr *fp;
- struct vattr va;
- struct vattr *vap = &va;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- caddr_t bpos;
- int error = 0, rdonly;
- struct mbuf *mb, *mreq;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(0);
- error = 0;
- goto nfsmout;
- }
- error = VOP_GETATTR(vp, vap, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
- if (error) {
- error = 0;
- goto nfsmout;
- }
- fp = nfsm_build(struct nfs_fattr *,
- NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
- nfsm_srvfillattr(vap, fp);
- /* fall through */
-
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs setattr service
- */
-int
-nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vattr va, preat;
- struct vattr *vap = &va;
- struct nfsv2_sattr *sp;
- struct nfs_fattr *fp;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
- struct mbuf *mb, *mreq;
- struct timespec guard = { 0, 0 };
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- VATTR_NULL(vap);
- if (v3) {
- nfsm_srvsattr(vap);
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- gcheck = fxdr_unsigned(int, *tl);
- if (gcheck) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
- fxdr_nfsv3time(tl, &guard);
- }
- } else {
- sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
- /*
- * Nah nah nah nah na nah
- * There is a bug in the Sun client that puts 0xffff in the mode
- * field of sattr when it should put in 0xffffffff. The u_short
- * doesn't sign extend.
- * --> check the low order 2 bytes for 0xffff
- */
- if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
- vap->va_mode = nfstov_mode(sp->sa_mode);
- if (sp->sa_uid != nfsrv_nfs_xdrneg1)
- vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
- if (sp->sa_gid != nfsrv_nfs_xdrneg1)
- vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
- if (sp->sa_size != nfsrv_nfs_xdrneg1)
- vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
- if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
-#ifdef notyet
- fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
-#else
- vap->va_atime.tv_sec =
- fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
- vap->va_atime.tv_nsec = 0;
-#endif
- }
- if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
- fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
-
- }
-
- /*
- * Now that we have all the fields, lets do it.
- */
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * vp now an active resource, pay careful attention to cleanup
- */
- if (v3) {
- error = preat_ret = VOP_GETATTR(vp, &preat, cred);
- if (!error && gcheck &&
- (preat.va_ctime.tv_sec != guard.tv_sec ||
- preat.va_ctime.tv_nsec != guard.tv_nsec))
- error = NFSERR_NOT_SYNC;
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * If the size is being changed write acces is required, otherwise
- * just check for a read only filesystem.
- */
- if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
- if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- error = EROFS;
- goto out;
- }
- } else {
- if (vp->v_type == VDIR) {
- error = EISDIR;
- goto out;
- } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
- 0)) != 0)
- goto out;
- }
- error = VOP_SETATTR(vp, vap, cred);
- postat_ret = VOP_GETATTR(vp, vap, cred);
- if (!error)
- error = postat_ret;
-out:
- if (vp != NULL)
- vput(vp);
-
- vp = NULL;
- nfsm_reply(NFSX_WCCORFATTR(v3));
- if (v3) {
- nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
- } else if (!error) {
- /* v2 non-error case. */
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs lookup rpc
- */
-int
-nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nfs_fattr *fp;
- struct nameidata nd, ind, *ndp = &nd;
- struct vnode *vp, *dirp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- caddr_t bpos;
- int error = 0, len, dirattr_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
- struct mbuf *mb, *mreq;
- struct vattr va, dirattr, *vap = &va;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- nfsm_srvnamesiz(len);
-
- pubflag = nfs_ispublicfh(fhp);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirattr, &dirattr_ret, pubflag);
-
- /*
- * namei failure, only dirp to cleanup. Clear out garbarge from
- * structure in case macros jump to nfsmout.
- */
-
- if (error) {
- if (dirp) {
- vrele(dirp);
- dirp = NULL;
- }
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Locate index file for public filehandle
- *
- * error is 0 on entry and 0 on exit from this block.
- */
-
- if (pubflag) {
- if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
- /*
- * Setup call to lookup() to see if we can find
- * the index file. Arguably, this doesn't belong
- * in a kernel.. Ugh. If an error occurs, do not
- * try to install an index file and then clear the
- * error.
- *
- * When we replace nd with ind and redirect ndp,
- * maintenance of ni_startdir and ni_vp shift to
- * ind and we have to clean them up in the old nd.
- * However, the cnd resource continues to be maintained
- * via the original nd. Confused? You aren't alone!
- */
- ind = nd;
- VOP_UNLOCK(nd.ni_vp, 0);
- ind.ni_pathlen = strlen(nfs_pub.np_index);
- ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
- nfs_pub.np_index;
- ind.ni_startdir = nd.ni_vp;
- VREF(ind.ni_startdir);
- error = lookup(&ind);
- ind.ni_dvp = NULL;
-
- if (error == 0) {
- /*
- * Found an index file. Get rid of
- * the old references. transfer nd.ni_vp'
- */
- if (dirp)
- vrele(dirp);
- dirp = nd.ni_vp;
- nd.ni_vp = NULL;
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- ndp = &ind;
- }
- error = 0;
- }
- /*
- * If the public filehandle was used, check that this lookup
- * didn't result in a filehandle outside the publicly exported
- * filesystem. We clear the poor vp here to avoid lockups due
- * to NFS I/O.
- */
-
- if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- error = EPERM;
- }
- }
-
- /*
- * Resources at this point:
- * ndp->ni_vp may not be NULL
- */
-
- if (error) {
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Get underlying attribute, then release remaining resources ( for
- * the same potential blocking reason ) and reply.
- */
- vp = ndp->ni_vp;
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(vp, vap, cred);
-
- vput(vp);
- vrele(ndp->ni_startdir);
- vrele(dirp);
- ndp->ni_vp = NULL;
- ndp->ni_startdir = NULL;
- dirp = NULL;
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
- if (error) {
- if (v3)
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- error = 0;
- goto nfsmout;
- }
- nfsm_srvfhtom(fhp, v3);
- if (v3) {
- nfsm_srvpostop_attr(0, vap);
- nfsm_srvpostop_attr(dirattr_ret, &dirattr);
- } else {
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
-
-nfsmout:
- if (ndp->ni_vp || dirp || ndp->ni_startdir) {
- if (ndp->ni_vp)
- vput(ndp->ni_vp);
- if (dirp)
- vrele(dirp);
- if (ndp->ni_startdir)
- vrele(ndp->ni_startdir);
- }
- NDFREE(&nd, NDF_ONLY_PNBUF);
- return (error);
-}
-
-/*
- * nfs readlink service
- */
-int
-nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
- struct iovec *ivp = iv;
- struct mbuf *mp;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, rdonly, i, tlen, len, getret;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mp3, *nmp, *mreq;
- struct vnode *vp = NULL;
- struct vattr attr;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- mp = NULL;
-#endif
- mp3 = NULL;
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- len = 0;
- i = 0;
- while (len < NFS_MAXPATHLEN) {
- MGET(nmp, M_WAITOK, MT_DATA);
- MCLGET(nmp, M_WAITOK);
- nmp->m_len = NFSMSIZ(nmp);
- if (len == 0)
- mp3 = mp = nmp;
- else {
- mp->m_next = nmp;
- mp = nmp;
- }
- if ((len + mp->m_len) > NFS_MAXPATHLEN) {
- mp->m_len = NFS_MAXPATHLEN - len;
- len = NFS_MAXPATHLEN;
- } else
- len += mp->m_len;
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- i++;
- ivp++;
- }
- uiop->uio_iov = iv;
- uiop->uio_iovcnt = i;
- uiop->uio_offset = 0;
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_READ;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = NULL;
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvpostop_attr(1, NULL);
- error = 0;
- goto nfsmout;
- }
- if (vp->v_type != VLNK) {
- if (v3)
- error = EINVAL;
- else
- error = ENXIO;
- } else
- error = VOP_READLINK(vp, uiop, cred);
- getret = VOP_GETATTR(vp, &attr, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
- if (v3)
- nfsm_srvpostop_attr(getret, &attr);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- if (uiop->uio_resid > 0) {
- len -= uiop->uio_resid;
- tlen = nfsm_rndup(len);
- nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
- }
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(len);
- mb->m_next = mp3;
- mp3 = NULL;
-nfsmout:
- if (mp3)
- m_freem(mp3);
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs read service
- */
-int
-nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct iovec *iv;
- struct iovec *iv2;
- struct mbuf *m;
- struct nfs_fattr *fp;
- u_int32_t *tl;
- int i;
- caddr_t bpos;
- int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
- int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
- struct mbuf *mb, *mreq;
- struct mbuf *m2;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
- struct vattr va, *vap = &va;
- struct nfsheur *nh;
- off_t off;
- int ioflag = 0;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if (v3) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
- off = fxdr_hyper(tl);
- } else {
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- off = (off_t)fxdr_unsigned(u_int32_t, *tl);
- }
- nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
-
- /*
- * Reference vp. If an error occurs, vp will be invalid, but we
- * have to NULL it just in case. The macros might goto nfsmout
- * as well.
- */
-
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- vp = NULL;
- nfsm_reply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvpostop_attr(1, NULL);
- error = 0;
- goto nfsmout;
- }
-
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- if (!error) {
- if ((error = nfsrv_access(vp, VREAD, cred, rdonly, 1)) != 0)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, 1);
- }
- getret = VOP_GETATTR(vp, vap, cred);
- if (!error)
- error = getret;
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, vap);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Calculate byte count to read
- */
- if (off >= vap->va_size)
- cnt = 0;
- else if ((off + reqlen) > vap->va_size)
- cnt = vap->va_size - off;
- else
- cnt = reqlen;
-
- nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
- if (v3) {
- tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
- *tl++ = nfsrv_nfs_true;
- fp = (struct nfs_fattr *)tl;
- tl += (NFSX_V3FATTR / sizeof (u_int32_t));
- } else {
- tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
- fp = (struct nfs_fattr *)tl;
- tl += (NFSX_V2FATTR / sizeof (u_int32_t));
- }
- len = left = nfsm_rndup(cnt);
- if (cnt > 0) {
- /*
- * Generate the mbuf list with the uio_iov ref. to it.
- */
- i = 0;
- m = m2 = mb;
- while (left > 0) {
- siz = min(M_TRAILINGSPACE(m), left);
- if (siz > 0) {
- left -= siz;
- i++;
- }
- if (left > 0) {
- MGET(m, M_WAITOK, MT_DATA);
- MCLGET(m, M_WAITOK);
- m->m_len = 0;
- m2->m_next = m;
- m2 = m;
- }
- }
- iv = malloc(i * sizeof (struct iovec),
- M_TEMP, M_WAITOK);
- uiop->uio_iov = iv2 = iv;
- m = mb;
- left = len;
- i = 0;
- while (left > 0) {
- if (m == NULL)
- panic("nfsrv_read iov");
- siz = min(M_TRAILINGSPACE(m), left);
- if (siz > 0) {
- iv->iov_base = mtod(m, caddr_t) + m->m_len;
- iv->iov_len = siz;
- m->m_len += siz;
- left -= siz;
- iv++;
- i++;
- }
- m = m->m_next;
- }
- uiop->uio_iovcnt = i;
- uiop->uio_offset = off;
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_READ;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = NULL;
- nh = nfsrv_sequential_heuristic(uiop, vp);
- ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
- error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
- if (error == 0)
- nh->nh_nextoff = uiop->uio_offset;
- free((caddr_t)iv2, M_TEMP);
- if (error || (getret = VOP_GETATTR(vp, vap, cred))) {
- if (!error)
- error = getret;
- m_freem(mreq);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, vap);
- error = 0;
- goto nfsmout;
- }
- } else
- uiop->uio_resid = 0;
- vput(vp);
- vp = NULL;
- nfsm_srvfillattr(vap, fp);
- tlen = len - uiop->uio_resid;
- cnt = cnt < tlen ? cnt : tlen;
- tlen = nfsm_rndup(cnt);
- if (len != tlen || tlen != cnt)
- nfsm_adj(mb, len - tlen, tlen - cnt);
- if (v3) {
- *tl++ = txdr_unsigned(cnt);
- if (cnt < reqlen)
- *tl++ = nfsrv_nfs_true;
- else
- *tl++ = nfsrv_nfs_false;
- }
- *tl = txdr_unsigned(cnt);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs write service
- */
-int
-nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct iovec *ivp;
- int i, cnt;
- struct mbuf *mp;
- struct nfs_fattr *fp;
- struct iovec *iv;
- struct vattr va, forat;
- struct vattr *vap = &va;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, rdonly, len, forat_ret = 1;
- int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
- int stable = NFSV3WRITE_FILESYNC;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL;
- struct nfsheur *nh;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io, *uiop = &io;
- off_t off;
- struct mount *mntp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (mrep == NULL) {
- *mrq = NULL;
- error = 0;
- goto nfsmout;
- }
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mntp, V_WAIT);
- vfs_rel(mntp); /* The write holds a ref. */
- if (v3) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
- off = fxdr_hyper(tl);
- tl += 3;
- stable = fxdr_unsigned(int, *tl++);
- } else {
- tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
- off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
- tl += 2;
- if (nfs_async)
- stable = NFSV3WRITE_UNSTABLE;
- }
- retlen = len = fxdr_unsigned(int32_t, *tl);
- cnt = i = 0;
-
- /*
- * For NFS Version 2, it is not obvious what a write of zero length
- * should do, but I might as well be consistent with Version 3,
- * which is to return ok so long as there are no permission problems.
- */
- if (len > 0) {
- zeroing = 1;
- mp = mrep;
- while (mp) {
- if (mp == md) {
- zeroing = 0;
- adjust = dpos - mtod(mp, caddr_t);
- mp->m_len -= adjust;
- if (mp->m_len > 0 && adjust > 0)
- mp->m_data += adjust;
- }
- if (zeroing)
- mp->m_len = 0;
- else if (mp->m_len > 0) {
- i += mp->m_len;
- if (i > len) {
- mp->m_len -= (i - len);
- zeroing = 1;
- }
- if (mp->m_len > 0)
- cnt++;
- }
- mp = mp->m_next;
- }
- }
- if (len > NFS_MAXDATA || len < 0 || i < len) {
- error = EIO;
- nfsm_reply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- vp = NULL;
- nfsm_reply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
- if (v3)
- forat_ret = VOP_GETATTR(vp, &forat, cred);
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- if (!error)
- error = nfsrv_access(vp, VWRITE, cred, rdonly, 1);
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- error = 0;
- goto nfsmout;
- }
-
- if (len > 0) {
- ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
- M_WAITOK);
- uiop->uio_iov = iv = ivp;
- uiop->uio_iovcnt = cnt;
- mp = mrep;
- while (mp) {
- if (mp->m_len > 0) {
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- ivp++;
- }
- mp = mp->m_next;
- }
-
- /*
- * XXX
- * The IO_METASYNC flag indicates that all metadata (and not just
- * enough to ensure data integrity) mus be written to stable storage
- * synchronously.
- * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
- */
- if (stable == NFSV3WRITE_UNSTABLE)
- ioflags = IO_NODELOCKED;
- else if (stable == NFSV3WRITE_DATASYNC)
- ioflags = (IO_SYNC | IO_NODELOCKED);
- else
- ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
- uiop->uio_resid = len;
- uiop->uio_rw = UIO_WRITE;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = NULL;
- uiop->uio_offset = off;
- nh = nfsrv_sequential_heuristic(uiop, vp);
- ioflags |= nh->nh_seqcount << IO_SEQSHIFT;
- error = VOP_WRITE(vp, uiop, ioflags, cred);
- if (error == 0)
- nh->nh_nextoff = uiop->uio_offset;
- /* Unlocked write. */
- nfsrvstats.srvvop_writes++;
- free((caddr_t)iv, M_TEMP);
- }
- aftat_ret = VOP_GETATTR(vp, vap, cred);
- vput(vp);
- vp = NULL;
- if (!error)
- error = aftat_ret;
-ereply:
- nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
- 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(retlen);
- /*
- * If nfs_async is set, then pretend the write was FILESYNC.
- */
- if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
- *tl++ = txdr_unsigned(stable);
- else
- *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
- /*
- * Actually, there is no need to txdr these fields,
- * but it may make the values more human readable,
- * for debugging purposes.
- */
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else if (!error) {
- /* v2 non-error case. */
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- error = 0;
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mntp);
- return(error);
-}
-
-/*
- * nfs create service
- * now does a truncate to 0 length via. setattr if it already exists
- */
-int
-nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nfs_fattr *fp;
- struct vattr va, dirfor, diraft;
- struct vattr *vap = &va;
- struct nfsv2_sattr *sp;
- u_int32_t *tl;
- struct nameidata nd;
- caddr_t bpos;
- int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
- struct mbuf *mb, *mreq;
- struct vnode *dirp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t tempsize;
- struct timespec cverf;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- rdev = 0;
-#endif
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
-
- /*
- * Call namei and do initial cleanup to get a few things
- * out of the way. If we get an initial error we cleanup
- * and return here to avoid special-casing the invalid nd
- * structure through the rest of the case. dirp may be
- * set even if an error occurs, but the nd structure will not
- * be valid at all if an error occurs so we have to invalidate it
- * prior to calling nfsm_reply ( which might goto nfsmout ).
- */
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * No error. Continue. State:
- *
- * startdir is valid ( we release this immediately )
- * dirp may be valid
- * nd.ni_vp may be valid
- * nd.ni_dvp is valid
- *
- * The error state is set through the code and we may also do some
- * opportunistic releasing of vnodes to avoid holding locks through
- * NFS I/O. The cleanup at the end is a catch-all
- */
-
- VATTR_NULL(vap);
- if (v3) {
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- how = fxdr_unsigned(int, *tl);
- switch (how) {
- case NFSV3CREATE_GUARDED:
- if (nd.ni_vp) {
- error = EEXIST;
- break;
- }
- /* fall through */
- case NFSV3CREATE_UNCHECKED:
- nfsm_srvsattr(vap);
- break;
- case NFSV3CREATE_EXCLUSIVE:
- tl = nfsm_dissect_nonblock(u_int32_t *,
- NFSX_V3CREATEVERF);
- /* Unique bytes, endianness is not important. */
- cverf.tv_sec = (int32_t)tl[0];
- cverf.tv_nsec = tl[1];
- exclusive_flag = 1;
- break;
- };
- vap->va_type = VREG;
- } else {
- sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
- vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
- if (vap->va_type == VNON)
- vap->va_type = VREG;
- vap->va_mode = nfstov_mode(sp->sa_mode);
- switch (vap->va_type) {
- case VREG:
- tsize = fxdr_unsigned(int32_t, sp->sa_size);
- if (tsize != -1)
- vap->va_size = (u_quad_t)tsize;
- break;
- case VCHR:
- case VBLK:
- case VFIFO:
- rdev = fxdr_unsigned(long, sp->sa_size);
- break;
- default:
- break;
- };
- }
-
- /*
- * Iff doesn't exist, create it
- * otherwise just truncate to 0 length
- * should I set the mode too ?
- *
- * The only possible error we can have at this point is EEXIST.
- * nd.ni_vp will also be non-NULL in that case.
- */
- if (nd.ni_vp == NULL) {
- if (vap->va_mode == (mode_t)VNOVAL)
- vap->va_mode = 0;
- if (vap->va_type == VREG || vap->va_type == VSOCK) {
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- else {
- if (exclusive_flag) {
- exclusive_flag = 0;
- VATTR_NULL(vap);
- vap->va_atime = cverf;
- error = VOP_SETATTR(nd.ni_vp, vap,
- cred);
- }
- }
- } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
- vap->va_type == VFIFO) {
- /*
- * NFSv2-specific code for creating device nodes
- * and fifos.
- *
- * Handle SysV FIFO node special cases. All other
- * devices require super user to access.
- */
- if (vap->va_type == VCHR && rdev == 0xffffffff)
- vap->va_type = VFIFO;
- if (vap->va_type != VFIFO &&
- (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV,
- 0))) {
- goto ereply;
- }
- vap->va_rdev = rdev;
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- goto ereply;
- }
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
-
- /*
- * release dvp prior to lookup
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
- /*
- * Setup for lookup.
- *
- * Even though LOCKPARENT was cleared, ni_dvp may
- * be garbage.
- */
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
- nd.ni_cnd.cn_thread = curthread;
- nd.ni_cnd.cn_cred = cred;
- error = lookup(&nd);
- nd.ni_dvp = NULL;
- if (error)
- goto ereply;
-
- if (nd.ni_cnd.cn_flags & ISSYMLINK) {
- error = EINVAL;
- goto ereply;
- }
- } else {
- error = ENXIO;
- }
- } else {
- if (vap->va_size != -1) {
- error = nfsrv_access(nd.ni_vp, VWRITE,
- cred, (nd.ni_cnd.cn_flags & RDONLY), 0);
- if (!error) {
- tempsize = vap->va_size;
- VATTR_NULL(vap);
- vap->va_size = tempsize;
- error = VOP_SETATTR(nd.ni_vp, vap, cred);
- }
- }
- }
-
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred);
- }
- if (v3) {
- if (exclusive_flag && !error &&
- bcmp(&cverf, &vap->va_atime, sizeof (cverf)))
- error = EEXIST;
- if (dirp == nd.ni_dvp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- else {
- /* Drop the other locks to avoid deadlock. */
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- nd.ni_dvp = NULL;
- nd.ni_vp = NULL;
-
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- }
-ereply:
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- } else if (!error) {
- /* v2 non-error case. */
- nfsm_srvfhtom(fhp, v3);
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- error = 0;
-
-nfsmout:
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- if (dirp)
- vrele(dirp);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs v3 mknod service
- */
-int
-nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- struct vattr *vap = &va;
- struct thread *td = curthread;
- u_int32_t *tl;
- struct nameidata nd;
- caddr_t bpos;
- int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
- u_int32_t major, minor;
- enum vtype vtyp;
- struct mbuf *mb, *mreq;
- struct vnode *vp, *dirp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct mount *mp = NULL;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (!v3)
- panic("nfsrv_mknod: v3 proc called on a v2 connection");
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE;
-
- /*
- * Handle nfs_namei() call. If an error occurs, the nd structure
- * is not valid. However, nfsm_*() routines may still jump to
- * nfsmout.
- */
-
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (error) {
- nfsm_reply(NFSX_WCCDATA(1));
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- vtyp = nfsv3tov_type(*tl);
- if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
- error = NFSERR_BADTYPE;
- goto out;
- }
- VATTR_NULL(vap);
- nfsm_srvsattr(vap);
- if (vtyp == VCHR || vtyp == VBLK) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
- major = fxdr_unsigned(u_int32_t, *tl++);
- minor = fxdr_unsigned(u_int32_t, *tl);
- vap->va_rdev = makedev(major, minor);
- }
-
- /*
- * Iff doesn't exist, create it.
- */
- if (nd.ni_vp) {
- error = EEXIST;
- goto out;
- }
- vap->va_type = vtyp;
- if (vap->va_mode == (mode_t)VNOVAL)
- vap->va_mode = 0;
- if (vtyp == VSOCK) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- } else {
- if (vtyp != VFIFO && (error = priv_check_cred(cred,
- PRIV_VFS_MKNOD_DEV, 0)))
- goto out;
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- if (error) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- goto out;
- }
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
-
- /*
- * Release dvp prior to lookup
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
- nd.ni_cnd.cn_thread = td;
- nd.ni_cnd.cn_cred = td->td_ucred;
- error = lookup(&nd);
- nd.ni_dvp = NULL;
-
- if (error)
- goto out;
- if (nd.ni_cnd.cn_flags & ISSYMLINK)
- error = EINVAL;
- }
-
- /*
- * send response, cleanup, return.
- */
-out:
- vp = nd.ni_vp;
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(vp, vap, cred);
- }
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
- }
- if (vp) {
- vput(vp);
- vp = NULL;
- nd.ni_vp = NULL;
- }
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (dirp) {
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- vput(dirp);
- }
-ereply:
- nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- }
- vn_finished_write(mp);
- return (0);
-nfsmout:
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- if (dirp)
- vrele(dirp);
- if (nd.ni_startdir)
- vrele(nd.ni_startdir);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs remove service
- */
-int
-nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nameidata nd;
- caddr_t bpos;
- int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *dirp;
- struct vattr dirfor, diraft;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
-
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error == 0) {
- if (nd.ni_vp->v_type == VDIR) {
- error = EPERM; /* POSIX */
- goto out;
- }
- /*
- * The root of a mounted filesystem cannot be deleted.
- */
- if (nd.ni_vp->v_vflag & VV_ROOT) {
- error = EBUSY;
- goto out;
- }
-out:
- if (!error) {
- error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- }
- }
- if (dirp && v3) {
- if (dirp == nd.ni_dvp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- else {
- /* Drop the other locks to avoid deadlock. */
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- nd.ni_dvp = NULL;
- nd.ni_vp = NULL;
-
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- vrele(dirp);
- dirp = NULL;
- }
-ereply:
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs rename service
- */
-int
-nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- caddr_t bpos;
- int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
- int tdirfor_ret = 1, tdiraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct nameidata fromnd, tond;
- struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
- struct vnode *tdirp = NULL;
- struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
- nfsfh_t fnfh, tnfh;
- fhandle_t *ffhp, *tfhp;
- uid_t saved_uid;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- fvp = NULL;
-#endif
- ffhp = &fnfh.fh_generic;
- tfhp = &tnfh.fh_generic;
-
- /*
- * Clear fields incase goto nfsmout occurs from macro.
- */
-
- ndclear(&fromnd);
- ndclear(&tond);
-
- nfsm_srvmtofh(ffhp);
- if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out1;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
- /*
- * Remember our original uid so that we can reset cr_uid before
- * the second nfs_namei() call, in case it is remapped.
- */
- saved_uid = cred->cr_uid;
- fromnd.ni_cnd.cn_cred = cred;
- fromnd.ni_cnd.cn_nameiop = DELETE;
- fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
- error = nfs_namei(&fromnd, nfsd, ffhp, len, slp, nam, &md,
- &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, FALSE);
- if (fdirp && !v3) {
- vrele(fdirp);
- fdirp = NULL;
- }
- if (error) {
- nfsm_reply(2 * NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
- nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
- }
- error = 0;
- goto nfsmout;
- }
- fvp = fromnd.ni_vp;
- nfsm_srvmtofh(tfhp);
- nfsm_srvnamesiz(len2);
- cred->cr_uid = saved_uid;
- tond.ni_cnd.cn_cred = cred;
- tond.ni_cnd.cn_nameiop = RENAME;
- tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
- error = nfs_namei(&tond, nfsd, tfhp, len2, slp, nam, &md,
- &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, FALSE);
- if (tdirp && !v3) {
- vrele(tdirp);
- tdirp = NULL;
- }
- if (error)
- goto out1;
-
- tdvp = tond.ni_dvp;
- tvp = tond.ni_vp;
- if (tvp != NULL) {
- if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
- if (v3)
- error = EEXIST;
- else
- error = EISDIR;
- goto out;
- } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
- if (v3)
- error = EEXIST;
- else
- error = ENOTDIR;
- goto out;
- }
- if (tvp->v_type == VDIR && tvp->v_mountedhere) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- }
- if (fvp->v_type == VDIR && fvp->v_mountedhere) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- if (fvp->v_mount != tdvp->v_mount) {
- if (v3)
- error = EXDEV;
- else
- error = ENOTEMPTY;
- goto out;
- }
- if (fvp == tdvp) {
- if (v3)
- error = EINVAL;
- else
- error = ENOTEMPTY;
- }
- /*
- * If source is the same as the destination (that is the
- * same vnode with the same name in the same directory),
- * then there is nothing to do.
- */
- if (fvp == tvp && fromnd.ni_dvp == tdvp &&
- fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
- !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
- fromnd.ni_cnd.cn_namelen))
- error = -1;
-out:
- if (!error) {
- /*
- * The VOP_RENAME function releases all vnode references &
- * locks prior to returning so we need to clear the pointers
- * to bypass cleanup code later on.
- */
- error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
- tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
- fromnd.ni_dvp = NULL;
- fromnd.ni_vp = NULL;
- tond.ni_dvp = NULL;
- tond.ni_vp = NULL;
- if (error) {
- NDFREE(&fromnd, NDF_ONLY_PNBUF);
- NDFREE(&tond, NDF_ONLY_PNBUF);
- }
- } else {
- if (error == -1)
- error = 0;
- }
- /* fall through */
-out1:
- nfsm_reply(2 * NFSX_WCCDATA(v3));
- if (v3) {
- /* Release existing locks to prevent deadlock. */
- if (tond.ni_dvp) {
- if (tond.ni_dvp == tond.ni_vp)
- vrele(tond.ni_dvp);
- else
- vput(tond.ni_dvp);
- }
- if (tond.ni_vp)
- vput(tond.ni_vp);
- tond.ni_dvp = NULL;
- tond.ni_vp = NULL;
-
- if (fdirp) {
- vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY);
- fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred);
- VOP_UNLOCK(fdirp, 0);
- }
- if (tdirp) {
- vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY);
- tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred);
- VOP_UNLOCK(tdirp, 0);
- }
- nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
- nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- /*
- * Clear out tond related fields
- */
- if (tond.ni_dvp) {
- if (tond.ni_dvp == tond.ni_vp)
- vrele(tond.ni_dvp);
- else
- vput(tond.ni_dvp);
- }
- if (tond.ni_vp)
- vput(tond.ni_vp);
- if (tdirp)
- vrele(tdirp);
- if (tond.ni_startdir)
- vrele(tond.ni_startdir);
- NDFREE(&tond, NDF_ONLY_PNBUF);
- /*
- * Clear out fromnd related fields
- */
- if (fdirp)
- vrele(fdirp);
- if (fromnd.ni_startdir)
- vrele(fromnd.ni_startdir);
- NDFREE(&fromnd, NDF_ONLY_PNBUF);
- if (fromnd.ni_dvp)
- vrele(fromnd.ni_dvp);
- if (fromnd.ni_vp)
- vrele(fromnd.ni_vp);
-
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs link service
- */
-int
-nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nameidata nd;
- caddr_t bpos;
- int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
- int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL, *xp, *dirp = NULL;
- struct vattr dirfor, diraft, at;
- nfsfh_t nfh, dnfh;
- fhandle_t *fhp, *dfhp;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- dfhp = &dnfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvmtofh(dfhp);
- nfsm_srvnamesiz(len);
-
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- }
- vp = NULL;
- error = 0;
- goto nfsmout;
- }
- if (v3)
- getret = VOP_GETATTR(vp, &at, cred);
- if (vp->v_type == VDIR) {
- error = EPERM; /* POSIX */
- goto out1;
- }
- VOP_UNLOCK(vp, 0);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
- error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error) {
- vrele(vp);
- vp = NULL;
- goto out2;
- }
- xp = nd.ni_vp;
- if (xp != NULL) {
- error = EEXIST;
- vrele(vp);
- vp = NULL;
- goto out2;
- }
- xp = nd.ni_dvp;
- if (vp->v_mount != xp->v_mount) {
- error = EXDEV;
- vrele(vp);
- vp = NULL;
- goto out2;
- }
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- /* fall through */
-
-out1:
- if (v3)
- getret = VOP_GETATTR(vp, &at, cred);
-out2:
- if (dirp) {
- if (dirp == nd.ni_dvp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- else {
- /* Release existing locks to prevent deadlock. */
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vrele(nd.ni_vp);
- nd.ni_dvp = NULL;
- nd.ni_vp = NULL;
-
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- }
-ereply:
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (vp)
- vput(vp);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (dirp)
- vrele(dirp);
- if (nd.ni_vp)
- vrele(nd.ni_vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs symbolic link service
- */
-int
-nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- struct nameidata nd;
- struct vattr *vap = &va;
- struct nfsv2_sattr *sp;
- char *bpos, *pathcp = NULL;
- struct uio io;
- struct iovec iv;
- int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *dirp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | NOCACHE;
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (error == 0) {
- VATTR_NULL(vap);
- if (v3)
- nfsm_srvsattr(vap);
- nfsm_srvpathsiz(len2);
- }
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error)
- goto out;
- pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
- iv.iov_base = pathcp;
- iv.iov_len = len2;
- io.uio_resid = len2;
- io.uio_offset = 0;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = NULL;
- nfsm_mtouio(&io, len2);
- if (!v3) {
- sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
- vap->va_mode = nfstov_mode(sp->sa_mode);
- }
- *(pathcp + len2) = '\0';
- if (nd.ni_vp) {
- error = EEXIST;
- goto out;
- }
-
- /*
- * issue symlink op. SAVESTART is set so the underlying path component
- * is only freed by the VOP if an error occurs.
- */
- if (vap->va_mode == (mode_t)VNOVAL)
- vap->va_mode = 0;
- error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
- if (error)
- NDFREE(&nd, NDF_ONLY_PNBUF);
- else
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- /*
- * releases directory prior to potential lookup op.
- */
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- if (error == 0) {
- if (v3) {
- /*
- * Issue lookup. Leave SAVESTART set so we can easily free
- * the name buffer later on.
- *
- * since LOCKPARENT is not set, ni_dvp will be garbage on
- * return whether an error occurs or not.
- */
- nd.ni_cnd.cn_nameiop = LOOKUP;
- nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
- nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
- nd.ni_cnd.cn_thread = curthread;
- nd.ni_cnd.cn_cred = cred;
- error = lookup(&nd);
- nd.ni_dvp = NULL;
-
- if (error == 0) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred);
- vput(nd.ni_vp);
- nd.ni_vp = NULL;
- }
- }
- }
-out:
- /*
- * These releases aren't strictly required, does even doing them
- * make any sense? XXX can nfsm_reply() block?
- */
- if (pathcp) {
- free(pathcp, M_TEMP);
- pathcp = NULL;
- }
- if (dirp) {
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- if (nd.ni_startdir) {
- vrele(nd.ni_startdir);
- nd.ni_startdir = NULL;
- }
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vrele(nd.ni_vp);
- if (nd.ni_startdir)
- vrele(nd.ni_startdir);
- if (dirp)
- vrele(dirp);
- if (pathcp)
- free(pathcp, M_TEMP);
-
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs mkdir service
- */
-int
-nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vattr va, dirfor, diraft;
- struct vattr *vap = &va;
- struct nfs_fattr *fp;
- struct nameidata nd;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *dirp = NULL;
- int vpexcl = 0;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = CREATE;
- nd.ni_cnd.cn_flags = LOCKPARENT | NOCACHE;
-
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- VATTR_NULL(vap);
- if (v3) {
- nfsm_srvsattr(vap);
- } else {
- tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
- vap->va_mode = nfstov_mode(*tl++);
- }
-
- /*
- * At this point nd.ni_dvp is referenced and exclusively locked and
- * nd.ni_vp, if it exists, is referenced but not locked.
- */
-
- vap->va_type = VDIR;
- if (nd.ni_vp != NULL) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- error = EEXIST;
- goto out;
- }
-
- /*
- * Issue mkdir op. Since SAVESTART is not set, the pathname
- * component is freed by the VOP call. This will fill-in
- * nd.ni_vp, reference, and exclusively lock it.
- */
- if (vap->va_mode == (mode_t)VNOVAL)
- vap->va_mode = 0;
- error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vpexcl = 1;
-
- vput(nd.ni_dvp);
- nd.ni_dvp = NULL;
-
- if (!error) {
- bzero((caddr_t)fhp, sizeof(nfh));
- fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
- if (!error)
- error = VOP_GETATTR(nd.ni_vp, vap, cred);
- }
-out:
- if (dirp) {
- if (dirp == nd.ni_dvp) {
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- } else {
- /* Release existing locks to prevent deadlock. */
- if (nd.ni_dvp) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp == nd.ni_vp && vpexcl)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp) {
- if (vpexcl)
- vput(nd.ni_vp);
- else
- vrele(nd.ni_vp);
- }
- nd.ni_dvp = NULL;
- nd.ni_vp = NULL;
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- }
- nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
- if (v3) {
- if (!error) {
- nfsm_srvpostop_fh(fhp);
- nfsm_srvpostop_attr(0, vap);
- }
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- } else if (!error) {
- /* v2 non-error case. */
- nfsm_srvfhtom(fhp, v3);
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(vap, fp);
- }
- error = 0;
- /* fall through */
-
-nfsmout:
- if (nd.ni_dvp) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp == nd.ni_vp && vpexcl)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp) {
- if (vpexcl)
- vput(nd.ni_vp);
- else
- vrele(nd.ni_vp);
- }
- if (dirp)
- vrele(dirp);
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * nfs rmdir service
- */
-int
-nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- caddr_t bpos;
- int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *vp, *dirp = NULL;
- struct vattr dirfor, diraft;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct nameidata nd;
- struct mount *mp = NULL;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- ndclear(&nd);
-
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto out;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- nfsm_srvnamesiz(len);
- nd.ni_cnd.cn_cred = cred;
- nd.ni_cnd.cn_nameiop = DELETE;
- nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
- error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
- &dirp, v3, &dirfor, &dirfor_ret, FALSE);
- if (dirp && !v3) {
- vrele(dirp);
- dirp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_WCCDATA(v3));
- if (v3)
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- error = 0;
- goto nfsmout;
- }
- vp = nd.ni_vp;
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- goto out;
- }
- /*
- * No rmdir "." please.
- */
- if (nd.ni_dvp == vp) {
- error = EINVAL;
- goto out;
- }
- /*
- * The root of a mounted filesystem cannot be deleted.
- */
- if (vp->v_vflag & VV_ROOT)
- error = EBUSY;
-out:
- /*
- * Issue or abort op. Since SAVESTART is not set, path name
- * component is freed by the VOP after either.
- */
- if (!error)
- error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
- NDFREE(&nd, NDF_ONLY_PNBUF);
-
- if (dirp) {
- if (dirp == nd.ni_dvp)
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- else {
- /* Release existing locks to prevent deadlock. */
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- nd.ni_dvp = NULL;
- nd.ni_vp = NULL;
- vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
- diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
- VOP_UNLOCK(dirp, 0);
- }
- }
- nfsm_reply(NFSX_WCCDATA(v3));
- error = 0;
- if (v3)
- nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
- /* fall through */
-
-nfsmout:
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp) {
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- }
- if (nd.ni_vp)
- vput(nd.ni_vp);
- if (dirp)
- vrele(dirp);
-
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs readdir service
- * - mallocs what it thinks is enough to read
- * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
- * - calls VOP_READDIR()
- * - loops around building the reply
- * if the output generated exceeds count break out of loop
- * The nfsm_clget macro is used here so that the reply will be packed
- * tightly in mbuf clusters.
- * - it only knows that it has encountered eof when the VOP_READDIR()
- * reads nothing
- * - as such one readdir rpc will return eof false although you are there
- * and then the next will return eof
- * - it trims out records with d_fileno == 0
- * this doesn't matter for Unix clients, but they might confuse clients
- * for other os'.
- * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
- * than requested, but this may not apply to all filesystems. For
- * example, client NFS does not { although it is never remote mounted
- * anyhow }
- * The alternate call nfsrv_readdirplus() does lookups as well.
- * PS: The NFS protocol spec. does not clarify what the "count" byte
- * argument is a count of.. just name strings and file id's or the
- * entire reply rpc or ...
- * I tried just file name and id sizes and it confused the Sun client,
- * so I am using the full rpc size now. The "paranoia.." comment refers
- * to including the status longwords that are not a part of the dir.
- * "entry" structures, but are in the rpc.
- */
-struct flrep {
- nfsuint64 fl_off;
- u_int32_t fl_postopok;
- u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
- u_int32_t fl_fhok;
- u_int32_t fl_fhsize;
- u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
-};
-
-int
-nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- char *bp, *be;
- struct mbuf *mp;
- struct dirent *dp;
- caddr_t cp;
- u_int32_t *tl;
- caddr_t bpos;
- struct mbuf *mb, *mreq;
- char *cpos, *cend, *rbuf;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct uio io;
- struct iovec iv;
- int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
- int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- u_quad_t off, toff, verf;
- u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
- int is_ufs;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if (v3) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
- toff = fxdr_hyper(tl);
- tl += 2;
- verf = fxdr_hyper(tl);
- tl += 2;
- } else {
- tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
- toff = fxdr_unsigned(u_quad_t, *tl++);
- verf = 0; /* shut up gcc */
- }
- off = toff;
- cnt = fxdr_unsigned(int, *tl);
- siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
- xfer = NFS_SRVMAXDATA(nfsd);
- if (cnt > xfer)
- cnt = xfer;
- if (siz > xfer)
- siz = xfer;
- fullsiz = siz;
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (!error && vp->v_type != VDIR) {
- error = ENOTDIR;
- vput(vp);
- vp = NULL;
- }
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Obtain lock on vnode for this section of the code
- */
- if (v3) {
- error = getret = VOP_GETATTR(vp, &at, cred);
-#if 0
- /*
- * XXX This check may be too strict for Solaris 2.5 clients.
- */
- if (!error && toff && verf && verf != at.va_filerev)
- error = NFSERR_BAD_COOKIE;
-#endif
- }
- if (!error)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
- if (error) {
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
- VOP_UNLOCK(vp, 0);
-
- /*
- * end section. Allocate rbuf and continue
- */
- rbuf = malloc(siz, M_TEMP, M_WAITOK);
-again:
- iv.iov_base = rbuf;
- iv.iov_len = fullsiz;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_offset = (off_t)off;
- io.uio_resid = fullsiz;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = NULL;
- eofflag = 0;
- if (cookies) {
- free((caddr_t)cookies, M_TEMP);
- cookies = NULL;
- }
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
- off = (off_t)io.uio_offset;
- if (!cookies && !error)
- error = NFSERR_PERM;
- if (v3) {
- getret = VOP_GETATTR(vp, &at, cred);
- if (!error)
- error = getret;
- }
- VOP_UNLOCK(vp, 0);
- if (error) {
- vrele(vp);
- vp = NULL;
- free((caddr_t)rbuf, M_TEMP);
- if (cookies)
- free((caddr_t)cookies, M_TEMP);
- nfsm_reply(NFSX_POSTOPATTR(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- if (io.uio_resid) {
- siz -= io.uio_resid;
-
- /*
- * If nothing read, return eof
- * rpc reply
- */
- if (siz == 0) {
- vrele(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
- 2 * NFSX_UNSIGNED);
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- tl += 2;
- } else
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = nfsrv_nfs_false;
- *tl = nfsrv_nfs_true;
- free((caddr_t)rbuf, M_TEMP);
- free((caddr_t)cookies, M_TEMP);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * Check for degenerate cases of nothing useful read.
- * If so go try again
- */
- cpos = rbuf;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
- cookiep = cookies;
- /*
- * For some reason FreeBSD's ufs_readdir() chooses to back the
- * directory offset up to a block boundary, so it is necessary to
- * skip over the records that precede the requested offset. This
- * requires the assumption that file offset cookies monotonically
- * increase.
- */
- while (cpos < cend && ncookies > 0 &&
- (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
- (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) {
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- if (cpos >= cend || ncookies == 0) {
- toff = off;
- siz = fullsiz;
- goto again;
- }
-
- len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
- if (v3) {
- nfsm_srvpostop_attr(getret, &at);
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- }
- mp = mb;
- bp = bpos;
- be = bp + M_TRAILINGSPACE(mp);
-
- /* Loop through the records and build reply */
- while (cpos < cend && ncookies > 0) {
- if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
- nlen = dp->d_namlen;
- rem = nfsm_rndup(nlen) - nlen;
- len += (4 * NFSX_UNSIGNED + nlen + rem);
- if (v3)
- len += 2 * NFSX_UNSIGNED;
- if (len > cnt) {
- eofflag = 0;
- break;
- }
- /*
- * Build the directory record xdr from
- * the dirent entry.
- */
- nfsm_clget;
- *tl = nfsrv_nfs_true;
- bp += NFSX_UNSIGNED;
- if (v3) {
- nfsm_clget;
- *tl = 0;
- bp += NFSX_UNSIGNED;
- }
- nfsm_clget;
- *tl = txdr_unsigned(dp->d_fileno);
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(nlen);
- bp += NFSX_UNSIGNED;
-
- /* And loop around copying the name */
- xfer = nlen;
- cp = dp->d_name;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp+xfer) > be)
- tsiz = be-bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- /* And null pad to an int32_t boundary. */
- for (i = 0; i < rem; i++)
- *bp++ = '\0';
- nfsm_clget;
-
- /* Finish off the record */
- if (v3) {
- *tl = 0;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- }
- *tl = txdr_unsigned(*cookiep);
- bp += NFSX_UNSIGNED;
- }
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- vrele(vp);
- vp = NULL;
- nfsm_clget;
- *tl = nfsrv_nfs_false;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- if (eofflag)
- *tl = nfsrv_nfs_true;
- else
- *tl = nfsrv_nfs_false;
- bp += NFSX_UNSIGNED;
- if (mp != mb) {
- if (bp < be)
- mp->m_len = bp - mtod(mp, caddr_t);
- } else
- mp->m_len += bp - bpos;
- free((caddr_t)rbuf, M_TEMP);
- free((caddr_t)cookies, M_TEMP);
-
-nfsmout:
- if (vp)
- vrele(vp);
- return(error);
-}
-
-int
-nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- char *bp, *be;
- struct mbuf *mp;
- struct dirent *dp;
- caddr_t cp;
- u_int32_t *tl;
- caddr_t bpos;
- struct mbuf *mb, *mreq;
- char *cpos, *cend, *rbuf;
- struct vnode *vp = NULL, *nvp;
- struct flrep fl;
- nfsfh_t nfh;
- fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
- struct uio io;
- struct iovec iv;
- struct vattr va, at, *vap = &va;
- struct nfs_fattr *fp;
- int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1;
- int vp_locked;
- int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
- u_quad_t off, toff, verf;
- u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- int usevget = 1;
- struct componentname cn;
- struct mount *mntp = NULL;
- int is_ufs;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- vp_locked = 0;
- if (!v3)
- panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
- toff = fxdr_hyper(tl);
- tl += 2;
- verf = fxdr_hyper(tl);
- tl += 2;
- siz = fxdr_unsigned(int, *tl++);
- cnt = fxdr_unsigned(int, *tl);
- off = toff;
- siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
- xfer = NFS_SRVMAXDATA(nfsd);
- if (cnt > xfer)
- cnt = xfer;
- if (siz > xfer)
- siz = xfer;
- fullsiz = siz;
- error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, nfsd, slp,
- nam, &rdonly);
- if (!error) {
- vp_locked = 1;
- mntp = vp->v_mount;
- if (vp->v_type != VDIR) {
- error = ENOTDIR;
- vput(vp);
- vp = NULL;
- vp_locked = 0;
- }
- }
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- error = getret = VOP_GETATTR(vp, &at, cred);
-#if 0
- /*
- * XXX This check may be too strict for Solaris 2.5 clients.
- */
- if (!error && toff && verf && verf != at.va_filerev)
- error = NFSERR_BAD_COOKIE;
-#endif
- if (!error)
- error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
- if (error) {
- vput(vp);
- vp_locked = 0;
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
- VOP_UNLOCK(vp, 0);
- vp_locked = 0;
- rbuf = malloc(siz, M_TEMP, M_WAITOK);
-again:
- iv.iov_base = rbuf;
- iv.iov_len = fullsiz;
- io.uio_iov = &iv;
- io.uio_iovcnt = 1;
- io.uio_offset = (off_t)off;
- io.uio_resid = fullsiz;
- io.uio_segflg = UIO_SYSSPACE;
- io.uio_rw = UIO_READ;
- io.uio_td = NULL;
- eofflag = 0;
- vp_locked = 1;
- if (cookies) {
- free((caddr_t)cookies, M_TEMP);
- cookies = NULL;
- }
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
- off = (u_quad_t)io.uio_offset;
- getret = VOP_GETATTR(vp, &at, cred);
- VOP_UNLOCK(vp, 0);
- vp_locked = 0;
- if (!cookies && !error)
- error = NFSERR_PERM;
- if (!error)
- error = getret;
- if (error) {
- vrele(vp);
- vp = NULL;
- if (cookies)
- free((caddr_t)cookies, M_TEMP);
- free((caddr_t)rbuf, M_TEMP);
- nfsm_reply(NFSX_V3POSTOPATTR);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- if (io.uio_resid) {
- siz -= io.uio_resid;
-
- /*
- * If nothing read, return eof
- * rpc reply
- */
- if (siz == 0) {
- vrele(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
- 2 * NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- tl += 2;
- *tl++ = nfsrv_nfs_false;
- *tl = nfsrv_nfs_true;
- free((caddr_t)cookies, M_TEMP);
- free((caddr_t)rbuf, M_TEMP);
- error = 0;
- goto nfsmout;
- }
- }
-
- /*
- * Check for degenerate cases of nothing useful read.
- * If so go try again
- */
- cpos = rbuf;
- cend = rbuf + siz;
- dp = (struct dirent *)cpos;
- cookiep = cookies;
- /*
- * For some reason FreeBSD's ufs_readdir() chooses to back the
- * directory offset up to a block boundary, so it is necessary to
- * skip over the records that precede the requested offset. This
- * requires the assumption that file offset cookies monotonically
- * increase.
- */
- while (cpos < cend && ncookies > 0 &&
- (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
- (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) {
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- if (cpos >= cend || ncookies == 0) {
- toff = off;
- siz = fullsiz;
- goto again;
- }
-
- dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
- 2 * NFSX_UNSIGNED;
- nfsm_reply(cnt);
- nfsm_srvpostop_attr(getret, &at);
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- txdr_hyper(at.va_filerev, tl);
- mp = mb;
- bp = bpos;
- be = bp + M_TRAILINGSPACE(mp);
-
- /* Loop through the records and build reply */
- while (cpos < cend && ncookies > 0) {
- if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
- nlen = dp->d_namlen;
- rem = nfsm_rndup(nlen)-nlen;
-
- if (usevget) {
- /*
- * For readdir_and_lookup get the vnode using
- * the file number.
- */
- error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED,
- &nvp);
- if (error != 0 && error != EOPNOTSUPP) {
- error = 0;
- goto invalid;
- } else if (error == EOPNOTSUPP) {
- /*
- * VFS_VGET() not supported?
- * Let's switch to VOP_LOOKUP().
- */
- error = 0;
- usevget = 0;
- cn.cn_nameiop = LOOKUP;
- cn.cn_flags = ISLASTCN | NOFOLLOW | \
- LOCKSHARED | LOCKLEAF;
- cn.cn_lkflags = LK_SHARED | LK_RETRY;
- cn.cn_cred = cred;
- cn.cn_thread = curthread;
- }
- }
- if (!usevget) {
- cn.cn_nameptr = dp->d_name;
- cn.cn_namelen = dp->d_namlen;
- if (dp->d_namlen == 2 &&
- dp->d_name[0] == '.' &&
- dp->d_name[1] == '.') {
- cn.cn_flags |= ISDOTDOT;
- } else {
- cn.cn_flags &= ~ISDOTDOT;
- }
- if (!vp_locked) {
- vn_lock(vp, LK_SHARED | LK_RETRY);
- vp_locked = 1;
- }
- if ((vp->v_vflag & VV_ROOT) != 0 &&
- (cn.cn_flags & ISDOTDOT) != 0) {
- vref(vp);
- nvp = vp;
- } else if (VOP_LOOKUP(vp, &nvp, &cn) != 0)
- goto invalid;
- }
-
- bzero((caddr_t)nfhp, NFSX_V3FH);
- nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid;
- if ((error1 = VOP_VPTOFH(nvp, &nfhp->fh_fid)) == 0)
- error1 = VOP_GETATTR(nvp, vap, cred);
- if (!usevget && vp == nvp)
- vunref(nvp);
- else
- vput(nvp);
- nvp = NULL;
- if (error1 != 0)
- goto invalid;
-
- /*
- * If either the dircount or maxcount will be
- * exceeded, get out now. Both of these lengths
- * are calculated conservatively, including all
- * XDR overheads.
- */
- len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
- NFSX_V3POSTOPATTR);
- dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
- if (len > cnt || dirlen > fullsiz) {
- eofflag = 0;
- break;
- }
-
- /*
- * Build the directory record xdr from
- * the dirent entry.
- */
- fp = (struct nfs_fattr *)&fl.fl_fattr;
- nfsm_srvfillattr(vap, fp);
- fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
- fl.fl_fhok = nfsrv_nfs_true;
- fl.fl_postopok = nfsrv_nfs_true;
- fl.fl_off.nfsuquad[0] = 0;
- fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
-
- nfsm_clget;
- *tl = nfsrv_nfs_true;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = 0;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(dp->d_fileno);
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- *tl = txdr_unsigned(nlen);
- bp += NFSX_UNSIGNED;
-
- /* And loop around copying the name */
- xfer = nlen;
- cp = dp->d_name;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp + xfer) > be)
- tsiz = be - bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- /* And null pad to an int32_t boundary. */
- for (i = 0; i < rem; i++)
- *bp++ = '\0';
-
- /*
- * Now copy the flrep structure out.
- */
- xfer = sizeof (struct flrep);
- cp = (caddr_t)&fl;
- while (xfer > 0) {
- nfsm_clget;
- if ((bp + xfer) > be)
- tsiz = be - bp;
- else
- tsiz = xfer;
- bcopy(cp, bp, tsiz);
- bp += tsiz;
- xfer -= tsiz;
- if (xfer > 0)
- cp += tsiz;
- }
- }
-invalid:
- cpos += dp->d_reclen;
- dp = (struct dirent *)cpos;
- cookiep++;
- ncookies--;
- }
- if (!usevget && vp_locked)
- vput(vp);
- else
- vrele(vp);
- vp = NULL;
- nfsm_clget;
- *tl = nfsrv_nfs_false;
- bp += NFSX_UNSIGNED;
- nfsm_clget;
- if (eofflag)
- *tl = nfsrv_nfs_true;
- else
- *tl = nfsrv_nfs_false;
- bp += NFSX_UNSIGNED;
- if (mp != mb) {
- if (bp < be)
- mp->m_len = bp - mtod(mp, caddr_t);
- } else
- mp->m_len += bp - bpos;
- free((caddr_t)cookies, M_TEMP);
- free((caddr_t)rbuf, M_TEMP);
-nfsmout:
- if (vp)
- vrele(vp);
- if (mntp)
- vfs_unbusy(mntp);
- return(error);
-}
-
-/*
- * nfs commit service
- */
-int
-nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct vattr bfor, aft;
- struct vnode *vp = NULL;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_int32_t *tl;
- caddr_t bpos;
- int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
- struct mbuf *mb, *mreq;
- u_quad_t off;
- struct mount *mp = NULL;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (!v3)
- panic("nfsrv_commit: v3 proc called on a v2 connection");
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
- error = ESTALE;
- goto ereply;
- }
- (void) vn_start_write(NULL, &mp, V_WAIT);
- vfs_rel(mp); /* The write holds a ref. */
- tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
-
- /*
- * XXX At this time VOP_FSYNC() does not accept offset and byte
- * count parameters, so these arguments are useless (someday maybe).
- */
- off = fxdr_hyper(tl);
- tl += 2;
- cnt = fxdr_unsigned(int, *tl);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(2 * NFSX_UNSIGNED);
- nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
- error = 0;
- goto nfsmout;
- }
- for_ret = VOP_GETATTR(vp, &bfor, cred);
-
- /*
- * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of file
- * is done. At this time VOP_FSYNC does not accept offset and byte count
- * parameters so call VOP_FSYNC the whole file for now.
- */
- if (cnt == 0 || cnt > MAX_COMMIT_COUNT) {
- /*
- * Give up and do the whole thing
- */
- if (vp->v_object &&
- (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- VM_OBJECT_WLOCK(vp->v_object);
- vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
- VM_OBJECT_WUNLOCK(vp->v_object);
- }
- error = VOP_FSYNC(vp, MNT_WAIT, curthread);
- } else {
- /*
- * Locate and synchronously write any buffers that fall
- * into the requested range. Note: we are assuming that
- * f_iosize is a power of 2.
- */
- int iosize = vp->v_mount->mnt_stat.f_iosize;
- int iomask = iosize - 1;
- struct bufobj *bo;
- daddr_t lblkno;
-
- /*
- * Align to iosize boundry, super-align to page boundry.
- */
- if (off & iomask) {
- cnt += off & iomask;
- off &= ~(u_quad_t)iomask;
- }
- if (off & PAGE_MASK) {
- cnt += off & PAGE_MASK;
- off &= ~(u_quad_t)PAGE_MASK;
- }
- lblkno = off / iosize;
-
- if (vp->v_object &&
- (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
- VM_OBJECT_WLOCK(vp->v_object);
- vm_object_page_clean(vp->v_object, off, off + cnt,
- OBJPC_SYNC);
- VM_OBJECT_WUNLOCK(vp->v_object);
- }
-
- bo = &vp->v_bufobj;
- BO_LOCK(bo);
- while (cnt > 0) {
- struct buf *bp;
-
- /*
- * If we have a buffer and it is marked B_DELWRI we
- * have to lock and write it. Otherwise the prior
- * write is assumed to have already been committed.
- *
- * gbincore() can return invalid buffers now so we
- * have to check that bit as well (though B_DELWRI
- * should not be set if B_INVAL is set there could be
- * a race here since we haven't locked the buffer).
- */
- if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
- LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) {
- BO_LOCK(bo);
- continue; /* retry */
- }
- if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
- B_DELWRI) {
- bremfree(bp);
- bp->b_flags &= ~B_ASYNC;
- bwrite(bp);
- ++nfs_commit_miss;
- } else
- BUF_UNLOCK(bp);
- BO_LOCK(bo);
- }
- ++nfs_commit_blks;
- if (cnt < iosize)
- break;
- cnt -= iosize;
- ++lblkno;
- }
- BO_UNLOCK(bo);
- }
-
- aft_ret = VOP_GETATTR(vp, &aft, cred);
- vput(vp);
- vp = NULL;
-ereply:
- nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
- nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
- if (!error) {
- tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else {
- error = 0;
- }
-nfsmout:
- if (vp)
- vput(vp);
- vn_finished_write(mp);
- return(error);
-}
-
-/*
- * nfs statfs service
- */
-int
-nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct statfs *sf;
- struct nfs_statfs *sfp;
- caddr_t bpos;
- int error = 0, rdonly, getret = 1;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- struct statfs statfs;
- u_quad_t tval;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- sf = &statfs;
- error = VFS_STATFS(vp->v_mount, sf);
- getret = VOP_GETATTR(vp, &at, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
- if (v3)
- nfsm_srvpostop_attr(getret, &at);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
- if (v3) {
- tval = (u_quad_t)sf->f_blocks;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_tbytes);
- tval = (u_quad_t)sf->f_bfree;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_fbytes);
- /*
- * Don't send negative values for available space,
- * since this field is unsigned in the NFS protocol.
- * Otherwise, the client would see absurdly high
- * numbers for free space.
- */
- if (sf->f_bavail < 0)
- tval = 0;
- else
- tval = (u_quad_t)sf->f_bavail;
- tval *= (u_quad_t)sf->f_bsize;
- txdr_hyper(tval, &sfp->sf_abytes);
- sfp->sf_tfiles.nfsuquad[0] = 0;
- sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
- sfp->sf_ffiles.nfsuquad[0] = 0;
- sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
- sfp->sf_afiles.nfsuquad[0] = 0;
- sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
- sfp->sf_invarsec = 0;
- } else {
- sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
- sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
- sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
- sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
- if (sf->f_bavail < 0)
- sfp->sf_bavail = 0;
- else
- sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
- }
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs fsinfo service
- */
-int
-nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nfsv3_fsinfo *sip;
- caddr_t bpos;
- int error = 0, rdonly, getret = 1, pref;
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- u_quad_t maxfsize;
- struct statfs sb;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (!v3)
- panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
-
- /* XXX Try to make a guess on the max file size. */
- VFS_STATFS(vp->v_mount, &sb);
- maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
-
- getret = VOP_GETATTR(vp, &at, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
- nfsm_srvpostop_attr(getret, &at);
- sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
-
- /*
- * XXX
- * There should be filesystem VFS OP(s) to get this information.
- * For now, assume ufs.
- */
- pref = NFS_SRVMAXDATA(nfsd);
- sip->fs_rtmax = txdr_unsigned(pref);
- sip->fs_rtpref = txdr_unsigned(pref);
- sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
- sip->fs_wtmax = txdr_unsigned(pref);
- sip->fs_wtpref = txdr_unsigned(pref);
- sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
- sip->fs_dtpref = txdr_unsigned(pref);
- txdr_hyper(maxfsize, &sip->fs_maxfilesize);
- sip->fs_timedelta.nfsv3_sec = 0;
- sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
- sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
- NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
- NFSV3FSINFO_CANSETTIME);
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * nfs pathconf service
- */
-int
-nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
- struct sockaddr *nam = nfsd->nd_nam;
- caddr_t dpos = nfsd->nd_dpos;
- struct ucred *cred = nfsd->nd_cr;
- struct nfsv3_pathconf *pc;
- caddr_t bpos;
- int error = 0, rdonly, getret = 1;
- register_t linkmax, namemax, chownres, notrunc;
- struct mbuf *mb, *mreq;
- struct vnode *vp = NULL;
- struct vattr at;
- nfsfh_t nfh;
- fhandle_t *fhp;
- int v3 = (nfsd->nd_flag & ND_NFSV3);
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (!v3)
- panic("nfsrv_pathconf: v3 proc called on a v2 connection");
- fhp = &nfh.fh_generic;
- nfsm_srvmtofh(fhp);
- error = nfsrv_fhtovp(fhp, 0, &vp, nfsd, slp, nam, &rdonly);
- if (error) {
- nfsm_reply(NFSX_UNSIGNED);
- nfsm_srvpostop_attr(getret, &at);
- error = 0;
- goto nfsmout;
- }
- error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
- if (!error)
- error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
- getret = VOP_GETATTR(vp, &at, cred);
- vput(vp);
- vp = NULL;
- nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
- nfsm_srvpostop_attr(getret, &at);
- if (error) {
- error = 0;
- goto nfsmout;
- }
- pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
-
- pc->pc_linkmax = txdr_unsigned(linkmax);
- pc->pc_namemax = txdr_unsigned(namemax);
- pc->pc_notrunc = txdr_unsigned(notrunc);
- pc->pc_chownrestricted = txdr_unsigned(chownres);
-
- /*
- * These should probably be supported by VOP_PATHCONF(), but
- * until msdosfs is exportable (why would you want to?), the
- * Unix defaults should be ok.
- */
- pc->pc_caseinsensitive = nfsrv_nfs_false;
- pc->pc_casepreserving = nfsrv_nfs_true;
-nfsmout:
- if (vp)
- vput(vp);
- return(error);
-}
-
-/*
- * Null operation, used by clients to ping server
- */
-/* ARGSUSED */
-int
-nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep;
- caddr_t bpos;
- int error = NFSERR_RETVOID;
- struct mbuf *mb, *mreq;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- nfsm_reply(0);
-nfsmout:
- return (error);
-}
-
-/*
- * No operation, used for obsolete procedures
- */
-/* ARGSUSED */
-int
-nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct mbuf *mrep = nfsd->nd_mrep;
- caddr_t bpos;
- int error;
- struct mbuf *mb, *mreq;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
- if (nfsd->nd_repstat)
- error = nfsd->nd_repstat;
- else
- error = EPROCUNAVAIL;
- nfsm_reply(0);
- error = 0;
-nfsmout:
- return (error);
-}
-
-/*
- * Perform access checking for vnodes obtained from file handles that would
- * refer to files already opened by a Unix client. You cannot just use
- * vn_writechk() and VOP_ACCESS() for two reasons.
- * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
- * case.
- * 2 - The owner is to be given access irrespective of mode bits for some
- * operations, so that processes that chmod after opening a file don't
- * break. I don't like this because it opens a security hole, but since
- * the nfs server opens a security hole the size of a barn door anyhow,
- * what the heck.
- *
- * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
- * will return EPERM instead of EACCES. EPERM is always an error.
- */
-static int
-nfsrv_access(struct vnode *vp, accmode_t accmode, struct ucred *cred,
- int rdonly, int override)
-{
- struct vattr vattr;
- int error;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-
- if (accmode & VWRITE) {
- /* Just vn_writechk() changed to check rdonly */
- /*
- * Disallow write attempts on read-only filesystems;
- * unless the file is a socket or a block or character
- * device resident on the filesystem.
- */
- if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
- /*
- * If there's shared text associated with
- * the inode, we can't allow writing.
- */
- if (VOP_IS_TEXT(vp))
- return (ETXTBSY);
- }
-
- error = VOP_GETATTR(vp, &vattr, cred);
- if (error)
- return (error);
- error = VOP_ACCESS(vp, accmode, cred, curthread);
- /*
- * Allow certain operations for the owner (reads and writes
- * on files that are already open).
- */
- if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
- error = 0;
- return (error);
-}
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
deleted file mode 100644
index 8bd045a..0000000
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_inet6.h"
-#include "opt_kgssapi.h"
-
-#include <sys/param.h>
-#include <sys/capsicum.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/jail.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/namei.h>
-#include <sys/fcntl.h>
-#include <sys/lockf.h>
-#include <sys/eventhandler.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#ifdef INET6
-#include <net/if.h>
-#include <net/if_var.h> /* XXX: for in6_var.h */
-#include <netinet6/in6_var.h> /* XXX: for ip6_sprintf */
-#endif
-
-#include <rpc/rpc.h>
-#include <rpc/rpcsec_gss.h>
-#include <rpc/replay.h>
-
-#include <nfs/xdr_subs.h>
-#include <nfs/nfsproto.h>
-#include <nfs/nfs_fha.h>
-#include <nfsserver/nfs.h>
-#include <nfsserver/nfsm_subs.h>
-#include <nfsserver/nfsrvcache.h>
-#include <nfsserver/nfs_fha_old.h>
-
-#include <security/mac/mac_framework.h>
-
-static MALLOC_DEFINE(M_NFSSVC, "nfss_srvsock", "Nfs server structure");
-
-MALLOC_DEFINE(M_NFSRVDESC, "nfss_srvdesc", "NFS server socket descriptor");
-MALLOC_DEFINE(M_NFSD, "nfss_daemon", "Nfs server daemon structure");
-
-#define TRUE 1
-#define FALSE 0
-
-SYSCTL_DECL(_vfs_nfsrv);
-
-SVCPOOL *nfsrv_pool;
-int nfsd_waiting = 0;
-int nfsrv_numnfsd = 0;
-struct callout nfsrv_callout;
-static eventhandler_tag nfsrv_nmbclusters_tag;
-
-static int nfs_privport = 0;
-SYSCTL_INT(_vfs_nfsrv, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW,
- &nfs_privport, 0,
- "Only allow clients using a privileged port");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay, CTLFLAG_RW,
- &nfsrvw_procrastinate, 0,
- "Delay value for write gathering");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay_v3, CTLFLAG_RW,
- &nfsrvw_procrastinate_v3, 0,
- "Delay in seconds for NFSv3 write gathering");
-
-static int nfssvc_addsock(struct file *, struct thread *);
-static int nfssvc_nfsd(struct thread *, struct nfsd_nfsd_args *);
-
-extern u_long sb_max_adj;
-
-int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
- struct nfssvc_sock *slp, struct mbuf **mreqp) = {
- nfsrv_null,
- nfsrv_getattr,
- nfsrv_setattr,
- nfsrv_lookup,
- nfsrv3_access,
- nfsrv_readlink,
- nfsrv_read,
- nfsrv_write,
- nfsrv_create,
- nfsrv_mkdir,
- nfsrv_symlink,
- nfsrv_mknod,
- nfsrv_remove,
- nfsrv_rmdir,
- nfsrv_rename,
- nfsrv_link,
- nfsrv_readdir,
- nfsrv_readdirplus,
- nfsrv_statfs,
- nfsrv_fsinfo,
- nfsrv_pathconf,
- nfsrv_commit,
- nfsrv_noop
-};
-
-/*
- * NFS server system calls
- */
-/*
- * This is now called from nfssvc() in nfs/nfs_nfssvc.c.
- */
-
-/*
- * Nfs server psuedo system call for the nfsd's
- * Based on the flag value it either:
- * - adds a socket to the selection list
- * - remains in the kernel as an nfsd
- * - remains in the kernel as an nfsiod
- * For INET6 we suppose that nfsd provides only IN6P_IPV6_V6ONLY sockets
- * and that mountd provides
- * - sockaddr with no IPv4-mapped addresses
- * - mask for both INET and INET6 families if there is IPv4-mapped overlap
- */
-int
-nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
-{
- struct file *fp;
- struct nfsd_addsock_args addsockarg;
- struct nfsd_nfsd_args nfsdarg;
- cap_rights_t rights;
- int error;
-
- if (uap->flag & NFSSVC_ADDSOCK) {
- error = copyin(uap->argp, (caddr_t)&addsockarg,
- sizeof(addsockarg));
- if (error)
- return (error);
- error = fget(td, addsockarg.sock,
- cap_rights_init(&rights, CAP_SOCK_SERVER), &fp);
- if (error)
- return (error);
- if (fp->f_type != DTYPE_SOCKET) {
- fdrop(fp, td);
- return (error); /* XXXRW: Should be EINVAL? */
- }
- error = nfssvc_addsock(fp, td);
- fdrop(fp, td);
- } else if (uap->flag & NFSSVC_OLDNFSD)
- error = nfssvc_nfsd(td, NULL);
- else if (uap->flag & NFSSVC_NFSD) {
- if (!uap->argp)
- return (EINVAL);
- error = copyin(uap->argp, (caddr_t)&nfsdarg,
- sizeof(nfsdarg));
- if (error)
- return (error);
- error = nfssvc_nfsd(td, &nfsdarg);
- } else
- error = ENXIO;
- return (error);
-}
-
-/*
- * Generate the rpc reply header
- * siz arg. is used to decide if adding a cluster is worthwhile
- */
-struct mbuf *
-nfs_rephead(int siz, struct nfsrv_descript *nd, int err,
- struct mbuf **mbp, caddr_t *bposp)
-{
- u_int32_t *tl;
- struct mbuf *mreq;
- caddr_t bpos;
- struct mbuf *mb;
-
- if (err == EBADRPC)
- return (NULL);
-
- nd->nd_repstat = err;
- if (err && (nd->nd_flag & ND_NFSV3) == 0) /* XXX recheck */
- siz = 0;
-
- MGET(mreq, M_WAITOK, MT_DATA);
-
- /*
- * If this is a big reply, use a cluster
- */
- mreq->m_len = 0;
- if (siz >= MINCLSIZE) {
- MCLGET(mreq, M_WAITOK);
- }
- mb = mreq;
- bpos = mtod(mb, caddr_t);
-
- if (err != NFSERR_RETVOID) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- if (err)
- *tl = txdr_unsigned(nfsrv_errmap(nd, err));
- else
- *tl = 0;
- }
-
- *mbp = mb;
- *bposp = bpos;
- if (err != 0 && err != NFSERR_RETVOID)
- nfsrvstats.srvrpc_errs++;
-
- return (mreq);
-}
-
-static void
-nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
-{
- rpcproc_t procnum;
- int32_t (*proc)(struct nfsrv_descript *nd, struct nfssvc_sock *slp,
- struct mbuf **mreqp);
- int flag;
- struct nfsrv_descript nd;
- struct mbuf *mreq, *mrep;
- int error;
-
- if (rqst->rq_vers == NFS_VER2) {
- if (rqst->rq_proc > NFSV2PROC_STATFS) {
- svcerr_noproc(rqst);
- svc_freereq(rqst);
- return;
- }
- procnum = nfsrv_nfsv3_procid[rqst->rq_proc];
- flag = 0;
- } else {
- if (rqst->rq_proc >= NFS_NPROCS) {
- svcerr_noproc(rqst);
- svc_freereq(rqst);
- return;
- }
- procnum = rqst->rq_proc;
- flag = ND_NFSV3;
- }
- proc = nfsrv3_procs[procnum];
-
- mreq = mrep = NULL;
- mreq = rqst->rq_args;
- rqst->rq_args = NULL;
- (void)nfs_realign(&mreq, M_WAITOK);
-
- /*
- * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 -
- * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP
- * mounts.
- */
- memset(&nd, 0, sizeof(nd));
- nd.nd_md = nd.nd_mrep = mreq;
- nd.nd_dpos = mtod(mreq, caddr_t);
- nd.nd_nam = svc_getrpccaller(rqst);
- nd.nd_nam2 = rqst->rq_addr;
- nd.nd_procnum = procnum;
- nd.nd_cr = NULL;
- nd.nd_flag = flag;
-
- if (nfs_privport) {
- /* Check if source port is privileged */
- u_short port;
- struct sockaddr *nam = nd.nd_nam;
- struct sockaddr_in *sin;
-
- sin = (struct sockaddr_in *)nam;
- /*
- * INET/INET6 - same code:
- * sin_port and sin6_port are at same offset
- */
- port = ntohs(sin->sin_port);
- if (port >= IPPORT_RESERVED &&
- nd.nd_procnum != NFSPROC_NULL) {
-#ifdef INET6
- char b6[INET6_ADDRSTRLEN];
-#if defined(KLD_MODULE)
- /* Do not use ip6_sprintf: the nfs module should work without INET6. */
-#define ip6_sprintf(buf, a) \
- (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \
- (a)->s6_addr16[0], (a)->s6_addr16[1], \
- (a)->s6_addr16[2], (a)->s6_addr16[3], \
- (a)->s6_addr16[4], (a)->s6_addr16[5], \
- (a)->s6_addr16[6], (a)->s6_addr16[7]), \
- (buf))
-#endif
-#endif
- printf("NFS request from unprivileged port (%s:%d)\n",
-#ifdef INET6
- sin->sin_family == AF_INET6 ?
- ip6_sprintf(b6, &satosin6(sin)->sin6_addr) :
-#if defined(KLD_MODULE)
-#undef ip6_sprintf
-#endif
-#endif
- inet_ntoa(sin->sin_addr), port);
- m_freem(mreq);
- svcerr_weakauth(rqst);
- svc_freereq(rqst);
- return;
- }
- }
-
- if (proc != nfsrv_null) {
- if (!svc_getcred(rqst, &nd.nd_cr, &nd.nd_credflavor)) {
- m_freem(mreq);
- svcerr_weakauth(rqst);
- svc_freereq(rqst);
- return;
- }
-#ifdef MAC
- mac_cred_associate_nfsd(nd.nd_cr);
-#endif
- }
- nfsrvstats.srvrpccnt[nd.nd_procnum]++;
-
- error = proc(&nd, NULL, &mrep);
-
- if (nd.nd_cr)
- crfree(nd.nd_cr);
-
- if (mrep == NULL) {
- svcerr_decode(rqst);
- svc_freereq(rqst);
- return;
- }
- if (error && error != NFSERR_RETVOID) {
- svcerr_systemerr(rqst);
- svc_freereq(rqst);
- return;
- }
- if (nd.nd_repstat & NFSERR_AUTHERR) {
- svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR);
- m_freem(mrep);
- } else {
- if (!svc_sendreply_mbuf(rqst, mrep))
- svcerr_systemerr(rqst);
- }
- svc_freereq(rqst);
-}
-
-/*
- * Adds a socket to the list for servicing by nfsds.
- */
-static int
-nfssvc_addsock(struct file *fp, struct thread *td)
-{
- int siz;
- struct socket *so;
- int error;
- SVCXPRT *xprt;
-
- so = fp->f_data;
-
- siz = sb_max_adj;
- error = soreserve(so, siz, siz);
- if (error)
- return (error);
-
- /*
- * Steal the socket from userland so that it doesn't close
- * unexpectedly.
- */
- if (so->so_type == SOCK_DGRAM)
- xprt = svc_dg_create(nfsrv_pool, so, 0, 0);
- else
- xprt = svc_vc_create(nfsrv_pool, so, 0, 0);
- if (xprt) {
- fp->f_ops = &badfileops;
- fp->f_data = NULL;
- svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL);
- svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL);
- SVC_RELEASE(xprt);
- }
-
- return (0);
-}
-
-/*
- * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
- * until it is killed by a signal.
- */
-static int
-nfssvc_nfsd(struct thread *td, struct nfsd_nfsd_args *args)
-{
- char principal[128];
- int error;
-
- if (args) {
- error = copyinstr(args->principal, principal,
- sizeof(principal), NULL);
- if (error)
- return (error);
- } else {
- memcpy(principal, "nfs@", 4);
- getcredhostname(td->td_ucred, principal + 4,
- sizeof(principal) - 4);
- }
-
- /*
- * Only the first nfsd actually does any work. The RPC code
- * adds threads to it as needed. Any extra processes offered
- * by nfsd just exit. If nfsd is new enough, it will call us
- * once with a structure that specifies how many threads to
- * use.
- */
- NFSD_LOCK();
- if (nfsrv_numnfsd == 0) {
- nfsrv_numnfsd++;
-
- NFSD_UNLOCK();
-
- rpc_gss_set_svc_name_call(principal, "kerberosv5",
- GSS_C_INDEFINITE, NFS_PROG, NFS_VER2);
- rpc_gss_set_svc_name_call(principal, "kerberosv5",
- GSS_C_INDEFINITE, NFS_PROG, NFS_VER3);
-
- if (args) {
- nfsrv_pool->sp_minthreads = args->minthreads;
- nfsrv_pool->sp_maxthreads = args->maxthreads;
- } else {
- nfsrv_pool->sp_minthreads = 4;
- nfsrv_pool->sp_maxthreads = 4;
- }
-
- svc_run(nfsrv_pool);
-
- rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER2);
- rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER3);
-
- NFSD_LOCK();
- nfsrv_numnfsd--;
- nfsrv_init(TRUE);
- }
- NFSD_UNLOCK();
-
- return (0);
-}
-
-/*
- * Size the NFS server's duplicate request cache at 1/2 the
- * nmbclusters, floating within a (64, 2048) range. This is to
- * prevent all mbuf clusters being tied up in the NFS dupreq
- * cache for small values of nmbclusters.
- */
-static size_t
-nfsrv_replay_size(void)
-{
- size_t replaysiz;
-
- replaysiz = nmbclusters / 2;
- if (replaysiz > NFSRVCACHE_MAX_SIZE)
- replaysiz = NFSRVCACHE_MAX_SIZE;
- if (replaysiz < NFSRVCACHE_MIN_SIZE)
- replaysiz = NFSRVCACHE_MIN_SIZE;
- replaysiz *= MCLBYTES;
-
- return (replaysiz);
-}
-
-/*
- * Called when nmbclusters changes - we resize the replay cache
- * accordingly.
- */
-static void
-nfsrv_nmbclusters_change(void *tag)
-{
-
- if (nfsrv_pool)
- replay_setsize(nfsrv_pool->sp_rcache, nfsrv_replay_size());
-}
-
-/*
- * Initialize the data structures for the server.
- * Handshake with any new nfsds starting up to avoid any chance of
- * corruption.
- */
-void
-nfsrv_init(int terminating)
-{
-
- NFSD_LOCK_ASSERT();
-
- if (terminating) {
- NFSD_UNLOCK();
- EVENTHANDLER_DEREGISTER(nmbclusters_change,
- nfsrv_nmbclusters_tag);
- svcpool_destroy(nfsrv_pool);
- nfsrv_pool = NULL;
- NFSD_LOCK();
- } else
- nfs_pub.np_valid = 0;
-
- NFSD_UNLOCK();
-
- nfsrv_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_nfsrv));
- nfsrv_pool->sp_rcache = replay_newcache(nfsrv_replay_size());
- nfsrv_pool->sp_assign = fhaold_assign;
- nfsrv_pool->sp_done = fha_nd_complete;
- nfsrv_nmbclusters_tag = EVENTHANDLER_REGISTER(nmbclusters_change,
- nfsrv_nmbclusters_change, NULL, EVENTHANDLER_PRI_FIRST);
-
- NFSD_LOCK();
-}
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
deleted file mode 100644
index 04371da..0000000
--- a/sys/nfsserver/nfs_srvsubs.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-/*-
- * 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.
- * 4. 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.
- *
- * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * These functions support the macros and help fiddle mbuf chains for
- * the nfs op functions. They do things like create the rpc header and
- * copy data between mbuf chains and uio lists.
- */
-
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/namei.h>
-#include <sys/mbuf.h>
-#include <sys/refcount.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/sysent.h>
-#include <sys/syscall.h>
-#include <sys/sysproto.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_extern.h>
-#include <vm/uma.h>
-
-#include <rpc/rpc.h>
-
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfsserver/nfsm_subs.h>
-
-#include <netinet/in.h>
-
-/*
- * Data items converted to xdr at startup, since they are constant
- * This is kinda hokey, but may save a little time doing byte swaps
- */
-u_int32_t nfsrv_nfs_xdrneg1;
-u_int32_t nfsrv_nfs_true, nfsrv_nfs_false;
-
-/* And other global data */
-static const nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR,
- NFLNK, NFNON, NFCHR, NFNON };
-#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
-#define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS)
-
-int nfsrv_ticks;
-
-struct mtx nfsd_mtx;
-
-/*
- * Mapping of old NFS Version 2 RPC numbers to generic numbers.
- */
-const int nfsrv_nfsv3_procid[NFS_NPROCS] = {
- NFSPROC_NULL,
- NFSPROC_GETATTR,
- NFSPROC_SETATTR,
- NFSPROC_NOOP,
- NFSPROC_LOOKUP,
- NFSPROC_READLINK,
- NFSPROC_READ,
- NFSPROC_NOOP,
- NFSPROC_WRITE,
- NFSPROC_CREATE,
- NFSPROC_REMOVE,
- NFSPROC_RENAME,
- NFSPROC_LINK,
- NFSPROC_SYMLINK,
- NFSPROC_MKDIR,
- NFSPROC_RMDIR,
- NFSPROC_READDIR,
- NFSPROC_FSSTAT,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
- NFSPROC_NOOP,
-};
-
-/*
- * and the reverse mapping from generic to Version 2 procedure numbers
- */
-const int nfsrvv2_procid[NFS_NPROCS] = {
- 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,
- NFSV2PROC_NOOP,
-};
-
-/*
- * Maps errno values to nfs error numbers.
- * Use 0 (which gets converted to NFSERR_IO) as the catch all for ones not
- * specifically defined in RFC 1094.
- */
-static const u_char nfsrv_v2errmap[ELAST] = {
- NFSERR_PERM, NFSERR_NOENT, 0, 0, 0,
- NFSERR_NXIO, 0, 0, 0, 0,
- 0, 0, NFSERR_ACCES, 0, 0,
- 0, NFSERR_EXIST, 0, NFSERR_NODEV, NFSERR_NOTDIR,
- NFSERR_ISDIR, 0, 0, 0, 0,
- 0, NFSERR_FBIG, NFSERR_NOSPC, 0, NFSERR_ROFS,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, NFSERR_NAMETOL, 0, 0,
- NFSERR_NOTEMPTY, 0, 0, NFSERR_DQUOT, NFSERR_STALE,
- 0
-};
-
-/*
- * Maps errno values to nfs error numbers.
- * Although it is not obvious whether or not NFS clients really care if
- * a returned error value is in the specified list for the procedure, the
- * safest thing to do is filter them appropriately. For Version 2, the
- * X/Open XNFS document is the only specification that defines error values
- * for each RPC (The RFC simply lists all possible error values for all RPCs),
- * so I have decided to not do this for Version 2.
- * The first entry is the default error return and the rest are the valid
- * errors for that RPC in increasing numeric order.
- */
-static const short nfsv3err_null[] = {
- 0,
- 0,
-};
-
-static const short nfsv3err_getattr[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_setattr[] = {
- NFSERR_IO,
- NFSERR_PERM,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOT_SYNC,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_lookup[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_access[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_readlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_read[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_NXIO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_write[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_INVAL,
- NFSERR_FBIG,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_create[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_mkdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_symlink[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_mknod[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- NFSERR_BADTYPE,
- 0,
-};
-
-static const short nfsv3err_remove[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_rmdir[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_ROFS,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_rename[] = {
- NFSERR_IO,
- NFSERR_NOENT,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_ISDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_NOTEMPTY,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_link[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_EXIST,
- NFSERR_XDEV,
- NFSERR_NOTDIR,
- NFSERR_INVAL,
- NFSERR_NOSPC,
- NFSERR_ROFS,
- NFSERR_MLINK,
- NFSERR_NAMETOL,
- NFSERR_DQUOT,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_NOTSUPP,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_readdir[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_readdirplus[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_ACCES,
- NFSERR_NOTDIR,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_BAD_COOKIE,
- NFSERR_NOTSUPP,
- NFSERR_TOOSMALL,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_fsstat[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_fsinfo[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_pathconf[] = {
- NFSERR_STALE,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short nfsv3err_commit[] = {
- NFSERR_IO,
- NFSERR_IO,
- NFSERR_STALE,
- NFSERR_BADHANDLE,
- NFSERR_SERVERFAULT,
- 0,
-};
-
-static const short *nfsrv_v3errmap[] = {
- nfsv3err_null,
- nfsv3err_getattr,
- nfsv3err_setattr,
- nfsv3err_lookup,
- nfsv3err_access,
- nfsv3err_readlink,
- nfsv3err_read,
- nfsv3err_write,
- nfsv3err_create,
- nfsv3err_mkdir,
- nfsv3err_symlink,
- nfsv3err_mknod,
- nfsv3err_remove,
- nfsv3err_rmdir,
- nfsv3err_rename,
- nfsv3err_link,
- nfsv3err_readdir,
- nfsv3err_readdirplus,
- nfsv3err_fsstat,
- nfsv3err_fsinfo,
- nfsv3err_pathconf,
- nfsv3err_commit,
-};
-
-extern int (*nfsd_call_nfsserver)(struct thread *, struct nfssvc_args *);
-
-/*
- * Called once to initialize data structures...
- */
-static int
-nfsrv_modevent(module_t mod, int type, void *data)
-{
- int error = 0;
-
- switch (type) {
- case MOD_LOAD:
- mtx_init(&nfsd_mtx, "nfsd_mtx", NULL, MTX_DEF);
- nfsrv_nfs_true = txdr_unsigned(TRUE);
- nfsrv_nfs_false = txdr_unsigned(FALSE);
- nfsrv_nfs_xdrneg1 = txdr_unsigned(-1);
- nfsrv_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
- if (nfsrv_ticks < 1)
- nfsrv_ticks = 1;
-
- NFSD_LOCK();
- nfsrv_init(0); /* Init server data structures */
- NFSD_UNLOCK();
-
- nfsd_call_nfsserver = nfssvc_nfsserver;
- break;
-
- case MOD_UNLOAD:
- if (nfsrv_numnfsd != 0) {
- error = EBUSY;
- break;
- }
-
- nfsd_call_nfsserver = NULL;
- callout_drain(&nfsrv_callout);
- mtx_destroy(&nfsd_mtx);
- break;
- default:
- error = EOPNOTSUPP;
- break;
- }
- return error;
-}
-static moduledata_t nfsserver_mod = {
- "nfsserver",
- nfsrv_modevent,
- NULL,
-};
-DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
-
-/* So that loader and kldload(2) can find us, wherever we are.. */
-MODULE_VERSION(nfsserver, 1);
-MODULE_DEPEND(nfsserver, nfssvc, 1, 1, 1);
-MODULE_DEPEND(nfsserver, krpc, 1, 1, 1);
-MODULE_DEPEND(nfsserver, nfs_common, 1, 1, 1);
-
-/*
- * Set up nameidata for a lookup() call and do it.
- *
- * If pubflag is set, this call is done for a lookup operation on the
- * public filehandle. In that case we allow crossing mountpoints and
- * absolute pathnames. However, the caller is expected to check that
- * the lookup result is within the public fs, and deny access if
- * it is not.
- *
- * nfs_namei() clears out garbage fields that namei() might leave garbage.
- * This is mainly ni_vp and ni_dvp when an error occurs, and ni_dvp when no
- * error occurs but the parent was not requested.
- *
- * dirp may be set whether an error is returned or not, and must be
- * released by the caller.
- */
-int
-nfs_namei(struct nameidata *ndp, struct nfsrv_descript *nfsd,
- fhandle_t *fhp, int len, struct nfssvc_sock *slp,
- struct sockaddr *nam, struct mbuf **mdp,
- caddr_t *dposp, struct vnode **retdirp, int v3, struct vattr *retdirattrp,
- int *retdirattr_retp, int pubflag)
-{
- int i, rem;
- struct mbuf *md;
- char *fromcp, *tocp, *cp;
- struct iovec aiov;
- struct uio auio;
- struct vnode *dp;
- int error, rdonly, linklen;
- struct componentname *cnp = &ndp->ni_cnd;
- int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0;
-
- *retdirp = NULL;
- cnp->cn_flags |= NOMACCHECK;
- cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
-
- /*
- * Copy the name from the mbuf list to ndp->ni_pnbuf
- * and set the various ndp fields appropriately.
- */
- fromcp = *dposp;
- tocp = cnp->cn_pnbuf;
- md = *mdp;
- rem = mtod(md, caddr_t) + md->m_len - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = md->m_next;
- if (md == NULL) {
- error = EBADRPC;
- goto out;
- }
- fromcp = mtod(md, caddr_t);
- rem = md->m_len;
- }
- if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
- error = EACCES;
- goto out;
- }
- *tocp++ = *fromcp++;
- rem--;
- }
- *tocp = '\0';
- *mdp = md;
- *dposp = fromcp;
- len = nfsm_rndup(len)-len;
- if (len > 0) {
- if (rem >= len)
- *dposp += len;
- else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
- goto out;
- }
-
- if (!pubflag && nfs_ispublicfh(fhp))
- return (ESTALE);
-
- /*
- * Extract and set starting directory.
- */
- error = nfsrv_fhtovp(fhp, 0, &dp, nfsd, slp, nam, &rdonly);
- if (error)
- goto out;
- if (dp->v_type != VDIR) {
- vput(dp);
- error = ENOTDIR;
- goto out;
- }
-
- if (rdonly)
- cnp->cn_flags |= RDONLY;
-
- /*
- * Set return directory. Reference to dp is implicitly transfered
- * to the returned pointer
- */
- *retdirp = dp;
- if (v3) {
- *retdirattr_retp = VOP_GETATTR(dp, retdirattrp,
- ndp->ni_cnd.cn_cred);
- }
-
- VOP_UNLOCK(dp, 0);
-
- if (pubflag) {
- /*
- * Oh joy. For WebNFS, handle those pesky '%' escapes,
- * and the 'native path' indicator.
- */
- cp = uma_zalloc(namei_zone, M_WAITOK);
- fromcp = cnp->cn_pnbuf;
- tocp = cp;
- if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
- switch ((unsigned char)*fromcp) {
- case WEBNFS_NATIVE_CHAR:
- /*
- * 'Native' path for us is the same
- * as a path according to the NFS spec,
- * just skip the escape char.
- */
- fromcp++;
- break;
- /*
- * More may be added in the future, range 0x80-0xff
- */
- default:
- error = EIO;
- uma_zfree(namei_zone, cp);
- goto out;
- }
- }
- /*
- * Translate the '%' escapes, URL-style.
- */
- while (*fromcp != '\0') {
- if (*fromcp == WEBNFS_ESC_CHAR) {
- if (fromcp[1] != '\0' && fromcp[2] != '\0') {
- fromcp++;
- *tocp++ = HEXSTRTOI(fromcp);
- fromcp += 2;
- continue;
- } else {
- error = ENOENT;
- uma_zfree(namei_zone, cp);
- goto out;
- }
- } else
- *tocp++ = *fromcp++;
- }
- *tocp = '\0';
- uma_zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- }
-
- ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
- ndp->ni_segflg = UIO_SYSSPACE;
-
- if (pubflag) {
- ndp->ni_rootdir = rootvnode;
- ndp->ni_loopcnt = 0;
-
- if (cnp->cn_pnbuf[0] == '/')
- dp = rootvnode;
- } else {
- cnp->cn_flags |= NOCROSSMOUNT;
- }
-
- /*
- * Initialize for scan, set ni_startdir and bump ref on dp again
- * because lookup() will dereference ni_startdir.
- */
-
- cnp->cn_thread = curthread;
- VREF(dp);
- ndp->ni_startdir = dp;
-
- if (!lockleaf)
- cnp->cn_flags |= LOCKLEAF;
- for (;;) {
- cnp->cn_nameptr = cnp->cn_pnbuf;
- /*
- * Call lookup() to do the real work. If an error occurs,
- * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
- * we do not have to dereference anything before returning.
- * In either case ni_startdir will be dereferenced and NULLed
- * out.
- */
- error = lookup(ndp);
- if (error)
- break;
-
- /*
- * Check for encountering a symbolic link. Trivial
- * termination occurs if no symlink encountered.
- * Note: zfree is safe because error is 0, so we will
- * not zfree it again when we break.
- */
- if ((cnp->cn_flags & ISSYMLINK) == 0) {
- if (cnp->cn_flags & (SAVENAME | SAVESTART))
- cnp->cn_flags |= HASBUF;
- else
- uma_zfree(namei_zone, cnp->cn_pnbuf);
- if (ndp->ni_vp && !lockleaf)
- VOP_UNLOCK(ndp->ni_vp, 0);
- break;
- }
-
- /*
- * Validate symlink
- */
- if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- VOP_UNLOCK(ndp->ni_dvp, 0);
- if (!pubflag) {
- error = EINVAL;
- goto badlink2;
- }
-
- if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
- error = ELOOP;
- goto badlink2;
- }
- if (ndp->ni_pathlen > 1)
- cp = uma_zalloc(namei_zone, M_WAITOK);
- else
- cp = cnp->cn_pnbuf;
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_td = NULL;
- auio.uio_resid = MAXPATHLEN;
- error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
- if (error) {
- badlink1:
- if (ndp->ni_pathlen > 1)
- uma_zfree(namei_zone, cp);
- badlink2:
- vput(ndp->ni_vp);
- vrele(ndp->ni_dvp);
- break;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen == 0) {
- error = ENOENT;
- goto badlink1;
- }
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- error = ENAMETOOLONG;
- goto badlink1;
- }
-
- /*
- * Adjust or replace path
- */
- if (ndp->ni_pathlen > 1) {
- bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
- uma_zfree(namei_zone, cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- } else
- cnp->cn_pnbuf[linklen] = '\0';
- ndp->ni_pathlen += linklen;
-
- /*
- * Cleanup refs for next loop and check if root directory
- * should replace current directory. Normally ni_dvp
- * becomes the new base directory and is cleaned up when
- * we loop. Explicitly null pointers after invalidation
- * to clarify operation.
- */
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
-
- if (cnp->cn_pnbuf[0] == '/') {
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = ndp->ni_rootdir;
- VREF(ndp->ni_dvp);
- }
- ndp->ni_startdir = ndp->ni_dvp;
- ndp->ni_dvp = NULL;
- }
- if (!lockleaf)
- cnp->cn_flags &= ~LOCKLEAF;
-
- /*
- * nfs_namei() guarentees that fields will not contain garbage
- * whether an error occurs or not. This allows the caller to track
- * cleanup state trivially.
- */
-out:
- if (error) {
- uma_zfree(namei_zone, cnp->cn_pnbuf);
- ndp->ni_vp = NULL;
- ndp->ni_dvp = NULL;
- ndp->ni_startdir = NULL;
- cnp->cn_flags &= ~HASBUF;
- } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
- ndp->ni_dvp = NULL;
- }
- return (error);
-}
-
-/*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
- */
-void
-nfsm_adj(struct mbuf *mp, int len, int nul)
-{
- struct mbuf *m;
- int count, i;
- char *cp;
-
- /*
- * Trim from tail. Scan the mbuf chain,
- * calculating its length and finding the last mbuf.
- * If the adjustment only affects this mbuf, then just
- * adjust and return. Otherwise, rescan and truncate
- * after the remaining size.
- */
- count = 0;
- m = mp;
- for (;;) {
- count += m->m_len;
- if (m->m_next == NULL)
- break;
- m = m->m_next;
- }
- if (m->m_len > len) {
- m->m_len -= len;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
- /*
- * Correct length for chain is "count".
- * Find the mbuf with last data, adjust its length,
- * and toss data from remaining mbufs on chain.
- */
- for (m = mp; m; m = m->m_next) {
- if (m->m_len >= count) {
- m->m_len = count;
- if (nul > 0) {
- cp = mtod(m, caddr_t)+m->m_len-nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
- }
- if (m->m_next != NULL) {
- m_freem(m->m_next);
- m->m_next = NULL;
- }
- break;
- }
- count -= m->m_len;
- }
-}
-
-/*
- * Make these functions instead of macros, so that the kernel text size
- * doesn't get too big...
- */
-void
-nfsm_srvwcc(struct nfsrv_descript *nfsd, int before_ret,
- struct vattr *before_vap, int after_ret, struct vattr *after_vap,
- struct mbuf **mbp, char **bposp)
-{
- struct mbuf *mb = *mbp;
- char *bpos = *bposp;
- u_int32_t *tl;
-
- if (before_ret) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = nfsrv_nfs_false;
- } else {
- tl = nfsm_build(u_int32_t *, 7 * NFSX_UNSIGNED);
- *tl++ = nfsrv_nfs_true;
- txdr_hyper(before_vap->va_size, tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_mtime), tl);
- tl += 2;
- txdr_nfsv3time(&(before_vap->va_ctime), tl);
- }
- *bposp = bpos;
- *mbp = mb;
- nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
-}
-
-void
-nfsm_srvpostopattr(struct nfsrv_descript *nfsd, int after_ret,
- struct vattr *after_vap, struct mbuf **mbp, char **bposp)
-{
- struct mbuf *mb = *mbp;
- char *bpos = *bposp;
- u_int32_t *tl;
- struct nfs_fattr *fp;
-
- if (after_ret) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- *tl = nfsrv_nfs_false;
- } else {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED + NFSX_V3FATTR);
- *tl++ = nfsrv_nfs_true;
- fp = (struct nfs_fattr *)tl;
- nfsm_srvfattr(nfsd, after_vap, fp);
- }
- *mbp = mb;
- *bposp = bpos;
-}
-
-void
-nfsm_srvfattr(struct nfsrv_descript *nfsd, struct vattr *vap,
- struct nfs_fattr *fp)
-{
-
- fp->fa_nlink = txdr_unsigned(vap->va_nlink);
- fp->fa_uid = txdr_unsigned(vap->va_uid);
- fp->fa_gid = txdr_unsigned(vap->va_gid);
- if (nfsd->nd_flag & ND_NFSV3) {
- fp->fa_type = vtonfsv3_type(vap->va_type);
- fp->fa_mode = vtonfsv3_mode(vap->va_mode);
- txdr_hyper(vap->va_size, &fp->fa3_size);
- txdr_hyper(vap->va_bytes, &fp->fa3_used);
- fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
- fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
- fp->fa3_fsid.nfsuquad[0] = 0;
- fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
- fp->fa3_fileid.nfsuquad[0] = 0;
- fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
- txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
- txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
- txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
- } else {
- fp->fa_type = vtonfsv2_type(vap->va_type);
- fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
- fp->fa2_size = txdr_unsigned(vap->va_size);
- fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
- if (vap->va_type == VFIFO)
- fp->fa2_rdev = 0xffffffff;
- else
- fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
- fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
- fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
- fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
- txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
- txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
- txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
- }
-}
-
-/*
- * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
- * - look up fsid in mount list (if not found ret error)
- * - get vp and export rights by calling VFS_FHTOVP()
- * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
- */
-int
-nfsrv_fhtovp(fhandle_t *fhp, int flags, struct vnode **vpp,
- struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
- struct sockaddr *nam, int *rdonlyp)
-{
- struct mount *mp;
- int i;
- struct ucred *cred, *credanon;
- int error, exflags;
-#ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */
- struct sockaddr_int *saddr;
-#endif
- int credflavor;
- int numsecflavors, *secflavors;
- int authsys;
- int v3 = nfsd->nd_flag & ND_NFSV3;
- int mountreq;
-
- *vpp = NULL;
-
- if (nfs_ispublicfh(fhp)) {
- if (!nfs_pub.np_valid)
- return (ESTALE);
- fhp = &nfs_pub.np_handle;
- }
-
- mp = vfs_busyfs(&fhp->fh_fsid);
- if (!mp)
- return (ESTALE);
- error = VFS_CHECKEXP(mp, nam, &exflags, &credanon,
- &numsecflavors, &secflavors);
- if (error) {
- vfs_unbusy(mp);
- goto out;
- }
- if (numsecflavors == 0) {
- /*
- * This can happen if the system is running with an
- * old mountd that doesn't pass in a secflavor list.
- */
- numsecflavors = 1;
- authsys = AUTH_SYS;
- secflavors = &authsys;
- }
- credflavor = nfsd->nd_credflavor;
- for (i = 0; i < numsecflavors; i++) {
- if (secflavors[i] == credflavor)
- break;
- }
- if (i == numsecflavors) {
- /*
- * RFC 2623 section 2.3.2 - allow certain procedures
- * used at NFS client mount time even if they have
- * weak authentication.
- */
- mountreq = FALSE;
- if (v3) {
- if (nfsd->nd_procnum == NFSPROC_FSINFO
- || nfsd->nd_procnum == NFSPROC_GETATTR)
- mountreq = TRUE;
- } else {
- if (nfsd->nd_procnum == NFSPROC_FSSTAT
- || nfsd->nd_procnum == NFSPROC_GETATTR)
- mountreq = TRUE;
- }
- if (!mountreq) {
- error = NFSERR_AUTHERR | AUTH_TOOWEAK;
- vfs_unbusy(mp);
- goto out;
- }
- }
- error = VFS_FHTOVP(mp, &fhp->fh_fid, LK_EXCLUSIVE, vpp);
- if (error) {
- /* Make sure the server replies ESTALE to the client. */
- error = ESTALE;
- vfs_unbusy(mp);
- goto out;
- }
-#ifdef MNT_EXNORESPORT
- if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
- saddr = (struct sockaddr_in *)nam;
- if ((saddr->sin_family == AF_INET ||
- saddr->sin_family == AF_INET6) &&
- /* same code for INET and INET6: sin*_port at same offet */
- ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
- vput(*vpp);
- *vpp = NULL;
- error = NFSERR_AUTHERR | AUTH_TOOWEAK;
- vfs_unbusy(mp);
- goto out;
- }
- }
-#endif
- /*
- * Check/setup credentials.
- */
- cred = nfsd->nd_cr;
- if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
- cred->cr_uid = credanon->cr_uid;
- crsetgroups(cred, credanon->cr_ngroups, credanon->cr_groups);
- }
- if (exflags & MNT_EXRDONLY)
- *rdonlyp = 1;
- else
- *rdonlyp = 0;
-
- if (!(flags & NFSRV_FLAG_BUSY))
- vfs_unbusy(mp);
-out:
- if (credanon != NULL)
- crfree(credanon);
-
- return (error);
-}
-
-
-/*
- * WebNFS: check if a filehandle is a public filehandle. For v3, this
- * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
- * transformed this to all zeroes in both cases, so check for it.
- */
-int
-nfs_ispublicfh(fhandle_t *fhp)
-{
- char *cp = (char *)fhp;
- int i;
-
- NFSD_LOCK_DONTCARE();
-
- for (i = 0; i < NFSX_V3FH; i++)
- if (*cp++ != 0)
- return (FALSE);
- return (TRUE);
-}
-
-/*
- * Map errnos to NFS error numbers. For Version 3 also filter out error
- * numbers not specified for the associated procedure.
- */
-int
-nfsrv_errmap(struct nfsrv_descript *nd, int err)
-{
- const short *defaulterrp, *errp;
- int e;
-
-
- if (nd->nd_flag & ND_NFSV3) {
- if (nd->nd_procnum <= NFSPROC_COMMIT) {
- errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
- while (*++errp) {
- if (*errp == err)
- return (err);
- else if (*errp > err)
- break;
- }
- return ((int)*defaulterrp);
- } else
- return (err & 0xffff);
- }
- e = 0;
- if (err <= ELAST)
- e = nfsrv_v2errmap[err - 1];
- if (e != 0)
- return (e);
- return (NFSERR_IO);
-}
-
-/*
- * Sort the group list in increasing numerical order.
- * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
- * that used to be here.)
- */
-void
-nfsrvw_sort(gid_t *list, int num)
-{
- int i, j;
- gid_t v;
-
- /* Insertion sort. */
- for (i = 1; i < num; i++) {
- v = list[i];
- /* find correct slot for value v, moving others up */
- for (j = i; --j >= 0 && v < list[j];)
- list[j + 1] = list[j];
- list[j + 1] = v;
- }
-}
-
-/*
- * Helper functions for macros.
- */
-
-void
-nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos)
-{
- u_int32_t *tl;
-
- if (v3) {
- tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
- *tl++ = txdr_unsigned(NFSX_V3FH);
- bcopy(f, tl, NFSX_V3FH);
- } else {
- tl = nfsm_build_xx(NFSX_V2FH, mb, bpos);
- bcopy(f, tl, NFSX_V2FH);
- }
-}
-
-void
-nfsm_srvpostop_fh_xx(fhandle_t *f, struct mbuf **mb, caddr_t *bpos)
-{
- u_int32_t *tl;
-
- tl = nfsm_build_xx(2 * NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
- *tl++ = nfsrv_nfs_true;
- *tl++ = txdr_unsigned(NFSX_V3FH);
- bcopy(f, tl, NFSX_V3FH);
-}
-
-int
-nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
-
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *s = fxdr_unsigned(int32_t, *tl);
- if (*s > m || *s <= 0)
- return EBADRPC;
- return 0;
-}
-
-int
-nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
-
- NFSD_LOCK_DONTCARE();
-
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *s = fxdr_unsigned(int32_t, *tl);
- if (*s > m)
- return NFSERR_NAMETOL;
- if (*s <= 0)
- return EBADRPC;
- return 0;
-}
-
-int
-nfsm_srvnamesiz0_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
-
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- *s = fxdr_unsigned(int32_t, *tl);
- if (*s > m)
- return NFSERR_NAMETOL;
- if (*s < 0)
- return EBADRPC;
- return 0;
-}
-
-void
-nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
- char **bp, char **be, caddr_t bpos)
-{
- struct mbuf *nmp;
-
- NFSD_UNLOCK_ASSERT();
-
- if (*bp >= *be) {
- if (*mp == mb)
- (*mp)->m_len += *bp - bpos;
- MGET(nmp, M_WAITOK, MT_DATA);
- MCLGET(nmp, M_WAITOK);
- nmp->m_len = NFSMSIZ(nmp);
- (*mp)->m_next = nmp;
- *mp = nmp;
- *bp = mtod(*mp, caddr_t);
- *be = *bp + (*mp)->m_len;
- }
- *tl = (u_int32_t *)*bp;
-}
-
-int
-nfsm_srvmtofh_xx(fhandle_t *f, int v3, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
- int fhlen;
-
- if (v3) {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- fhlen = fxdr_unsigned(int, *tl);
- if (fhlen != 0 && fhlen != NFSX_V3FH)
- return EBADRPC;
- } else {
- fhlen = NFSX_V2FH;
- }
- if (fhlen != 0) {
- tl = nfsm_dissect_xx_nonblock(fhlen, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- bcopy((caddr_t)tl, (caddr_t)(f), fhlen);
- } else {
- bzero((caddr_t)(f), NFSX_V3FH);
- }
- return 0;
-}
-
-int
-nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
-{
- u_int32_t *tl;
- int toclient = 0;
-
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*tl == nfsrv_nfs_true) {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- (a)->va_mode = nfstov_mode(*tl);
- }
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*tl == nfsrv_nfs_true) {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- (a)->va_uid = fxdr_unsigned(uid_t, *tl);
- }
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*tl == nfsrv_nfs_true) {
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- (a)->va_gid = fxdr_unsigned(gid_t, *tl);
- }
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- if (*tl == nfsrv_nfs_true) {
- tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- (a)->va_size = fxdr_hyper(tl);
- }
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- switch (fxdr_unsigned(int, *tl)) {
- case NFSV3SATTRTIME_TOCLIENT:
- tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- fxdr_nfsv3time(tl, &(a)->va_atime);
- toclient = 1;
- break;
- case NFSV3SATTRTIME_TOSERVER:
- vfs_timestamp(&a->va_atime);
- a->va_vaflags |= VA_UTIMES_NULL;
- break;
- }
- tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- switch (fxdr_unsigned(int, *tl)) {
- case NFSV3SATTRTIME_TOCLIENT:
- tl = nfsm_dissect_xx_nonblock(2 * NFSX_UNSIGNED, md, dpos);
- if (tl == NULL)
- return EBADRPC;
- fxdr_nfsv3time(tl, &(a)->va_mtime);
- a->va_vaflags &= ~VA_UTIMES_NULL;
- break;
- case NFSV3SATTRTIME_TOSERVER:
- vfs_timestamp(&a->va_mtime);
- if (toclient == 0)
- a->va_vaflags |= VA_UTIMES_NULL;
- break;
- }
- return 0;
-}
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index 354c63b..2f30d6d 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -177,7 +177,7 @@ trap(struct trapframe *frame)
* handled the trap and modified the trap frame so that this
* function can return normally.
*/
- if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame))
+ if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type) != 0)
return;
#endif
diff --git a/sys/sys/dtrace_bsd.h b/sys/sys/dtrace_bsd.h
index 6bcaf29..f46b900 100644
--- a/sys/sys/dtrace_bsd.h
+++ b/sys/sys/dtrace_bsd.h
@@ -39,14 +39,14 @@ struct vattr;
struct vnode;
struct reg;
-int dtrace_trap(struct trapframe *);
+int dtrace_trap(struct trapframe *, u_int);
/*
* The dtrace module handles traps that occur during a DTrace probe.
* This type definition is used in the trap handler to provide a
* hook for the dtrace module to register its handler with.
*/
-typedef int (*dtrace_trap_func_t)(struct trapframe *);
+typedef int (*dtrace_trap_func_t)(struct trapframe *, u_int);
extern dtrace_trap_func_t dtrace_trap_func;
/*
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index ac3cfb2..cbb2a18 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -757,7 +757,10 @@ static __inline void
m_clrprotoflags(struct mbuf *m)
{
- m->m_flags &= ~M_PROTOFLAGS;
+ while (m) {
+ m->m_flags &= ~M_PROTOFLAGS;
+ m = m->m_next;
+ }
}
static __inline struct mbuf *
diff --git a/sys/sys/param.h b/sys/sys/param.h
index d25cdef..a4922f1 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100050 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100051 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index f52bc0c..0ea259b 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -37,7 +37,7 @@ struct semid_ds_old {
long sem_pad1; /* SVABI/386 says I need this here */
time_t sem_ctime; /* last change time */
/* Times measured in secs since */
- /* 00:00:00 GMT, Jan. 1, 1970 */
+ /* 00:00:00 UTC, Jan. 1, 1970, without leap seconds */
long sem_pad2; /* SVABI/386 says I need this here */
long sem_pad3[4]; /* SVABI/386 says I need this here */
};
@@ -50,7 +50,7 @@ struct semid_ds {
time_t sem_otime; /* last operation time */
time_t sem_ctime; /* last change time */
/* Times measured in secs since */
- /* 00:00:00 GMT, Jan. 1, 1970 */
+ /* 00:00:00 UTC, Jan. 1, 1970, without leap seconds */
};
/*
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 1f0a530..395e888 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -398,7 +398,7 @@ extern sbintime_t sbt_tickthreshold;
* Functions containing "up" returns time relative to boot and
* should be used for calculating time intervals.
*
- * Functions without "up" returns GMT time.
+ * Functions without "up" returns UTC time.
*
* Functions with the "get" prefix returns a less precise result
* much faster than the functions without "get" prefix and should
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 87382b8..8a14f69 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -580,6 +580,7 @@ typedef void vop_getpages_iodone_t(void *, vm_page_t *, int, int);
/* vn_open_flags */
#define VN_OPEN_NOAUDIT 0x00000001
#define VN_OPEN_NOCAPCHECK 0x00000002
+#define VN_OPEN_NAMECACHE 0x00000004
/*
* Public vnode manipulation functions.
diff --git a/sys/teken/libteken/teken.3 b/sys/teken/libteken/teken.3
index 1c2ebbe..70bed07 100644
--- a/sys/teken/libteken/teken.3
+++ b/sys/teken/libteken/teken.3
@@ -188,7 +188,7 @@ prior to 9.0.
.Sh SEE ALSO
.Xr ncurses 3 ,
.Xr termcap 3 ,
-.Xr syscons 4 .
+.Xr syscons 4
.Sh HISTORY
The
.Nm
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index 21d4ba4..3d7a21d 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -205,8 +205,10 @@ ufs_create(ap)
error =
ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
ap->a_dvp, ap->a_vpp, ap->a_cnp);
- if (error)
+ if (error != 0)
return (error);
+ if ((ap->a_cnp->cn_flags & MAKEENTRY) != 0)
+ cache_enter(ap->a_dvp, *ap->a_vpp, ap->a_cnp);
return (0);
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index b2877c1..79665ba 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2711,6 +2711,8 @@ retrylookup:
sleep = (allocflags & VM_ALLOC_IGN_SBUSY) != 0 ?
vm_page_xbusied(m) : vm_page_busied(m);
if (sleep) {
+ if ((allocflags & VM_ALLOC_NOWAIT) != 0)
+ return (NULL);
/*
* Reference the page before unlocking and
* sleeping so that the page daemon is less
@@ -2736,8 +2738,10 @@ retrylookup:
return (m);
}
}
- m = vm_page_alloc(object, pindex, allocflags & ~VM_ALLOC_IGN_SBUSY);
+ m = vm_page_alloc(object, pindex, allocflags);
if (m == NULL) {
+ if ((allocflags & VM_ALLOC_NOWAIT) != 0)
+ return (NULL);
VM_OBJECT_WUNLOCK(object);
VM_WAIT;
VM_OBJECT_WLOCK(object);
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index f12b76c..cd30772 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -376,22 +376,36 @@ extern long first_page; /* first physical page number */
vm_page_t PHYS_TO_VM_PAGE(vm_paddr_t pa);
-/* page allocation classes: */
+/*
+ * Page allocation parameters for vm_page for the functions
+ * vm_page_alloc(), vm_page_grab(), vm_page_alloc_contig() and
+ * vm_page_alloc_freelist(). Some functions support only a subset
+ * of the flags, and ignore others, see the flags legend.
+ *
+ * Bits 0 - 1 define class.
+ * Bits 2 - 15 dedicated for flags.
+ * Legend:
+ * (a) - vm_page_alloc() supports the flag.
+ * (c) - vm_page_alloc_contig() supports the flag.
+ * (f) - vm_page_alloc_freelist() supports the flag.
+ * (g) - vm_page_grab() supports the flag.
+ * Bits above 15 define the count of additional pages that the caller
+ * intends to allocate.
+ */
#define VM_ALLOC_NORMAL 0
#define VM_ALLOC_INTERRUPT 1
#define VM_ALLOC_SYSTEM 2
#define VM_ALLOC_CLASS_MASK 3
-/* page allocation flags: */
-#define VM_ALLOC_WIRED 0x0020 /* non pageable */
-#define VM_ALLOC_ZERO 0x0040 /* Try to obtain a zeroed page */
-#define VM_ALLOC_NOOBJ 0x0100 /* No associated object */
-#define VM_ALLOC_NOBUSY 0x0200 /* Do not busy the page */
-#define VM_ALLOC_IFCACHED 0x0400 /* Fail if the page is not cached */
-#define VM_ALLOC_IFNOTCACHED 0x0800 /* Fail if the page is cached */
-#define VM_ALLOC_IGN_SBUSY 0x1000 /* vm_page_grab() only */
-#define VM_ALLOC_NODUMP 0x2000 /* don't include in dump */
-#define VM_ALLOC_SBUSY 0x4000 /* Shared busy the page */
-
+#define VM_ALLOC_WIRED 0x0020 /* (acfg) Allocate non pageable page */
+#define VM_ALLOC_ZERO 0x0040 /* (acfg) Try to obtain a zeroed page */
+#define VM_ALLOC_NOOBJ 0x0100 /* (acg) No associated object */
+#define VM_ALLOC_NOBUSY 0x0200 /* (acg) Do not busy the page */
+#define VM_ALLOC_IFCACHED 0x0400 /* (ag) Fail if page is not cached */
+#define VM_ALLOC_IFNOTCACHED 0x0800 /* (ag) Fail if page is cached */
+#define VM_ALLOC_IGN_SBUSY 0x1000 /* (g) Ignore shared busy flag */
+#define VM_ALLOC_NODUMP 0x2000 /* (ag) don't include in dump */
+#define VM_ALLOC_SBUSY 0x4000 /* (acg) Shared busy the page */
+#define VM_ALLOC_NOWAIT 0x8000 /* (g) Do not sleep, return NULL */
#define VM_ALLOC_COUNT_SHIFT 16
#define VM_ALLOC_COUNT(count) ((count) << VM_ALLOC_COUNT_SHIFT)
OpenPOWER on IntegriCloud