summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/conf/GENERIC10
-rw-r--r--sys/arm/arm/machdep.c32
-rw-r--r--sys/arm/arm/pl310.c42
-rw-r--r--sys/arm/arm/pmap-v6.c45
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fb.c2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_machdep.c19
-rw-r--r--sys/arm/conf/BEAGLEBONE6
-rw-r--r--sys/arm/include/atomic.h22
-rw-r--r--sys/arm/include/machdep.h4
-rw-r--r--sys/arm/include/pl310.h1
-rw-r--r--sys/arm/include/pmap.h2
-rw-r--r--sys/arm/ti/cpsw/if_cpsw.c75
-rw-r--r--sys/arm/ti/cpsw/if_cpswvar.h4
-rw-r--r--sys/arm/ti/ti_cpuid.c68
-rw-r--r--sys/arm/ti/ti_cpuid.h52
-rw-r--r--sys/arm/versatile/versatile_clcd.c2
-rw-r--r--sys/boot/common/interp_forth.c5
-rw-r--r--sys/conf/options.mips1
-rw-r--r--sys/contrib/octeon-sdk/cvmx-app-init.h6
-rw-r--r--sys/contrib/octeon-sdk/cvmx-helper-board.c9
-rw-r--r--sys/dev/ath/if_ath_rx.c17
-rw-r--r--sys/dev/ath/if_ath_spectral.c18
-rw-r--r--sys/dev/ath/if_athvar.h2
-rw-r--r--sys/dev/nvme/nvme_test.c4
-rw-r--r--sys/dev/pci/pci.c2
-rw-r--r--sys/dev/usb/controller/xhci.c29
-rw-r--r--sys/dev/usb/wlan/if_run.c16
-rw-r--r--sys/dev/xen/control/control.c24
-rw-r--r--sys/dev/xen/evtchn/evtchn_dev.c394
-rw-r--r--sys/dev/xen/netfront/netfront.c58
-rw-r--r--sys/dev/xen/xenpci/machine_reboot.c80
-rwxr-xr-xsys/fs/ext2fs/ext2_dinode.h39
-rw-r--r--sys/fs/fuse/fuse_io.c8
-rw-r--r--sys/fs/nandfs/nandfs_segment.c32
-rw-r--r--sys/fs/nullfs/null.h8
-rw-r--r--sys/fs/nullfs/null_subr.c3
-rw-r--r--sys/fs/nullfs/null_vfsops.c50
-rw-r--r--sys/fs/nullfs/null_vnops.c15
-rw-r--r--sys/fs/tmpfs/tmpfs.h168
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c557
-rw-r--r--sys/fs/tmpfs/tmpfs_vfsops.c15
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c110
-rw-r--r--sys/i386/conf/GENERIC10
-rw-r--r--sys/i386/xen/xen_machdep.c2
-rw-r--r--sys/ia64/conf/GENERIC7
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_lock.c2
-rw-r--r--sys/kern/kern_synch.c6
-rw-r--r--sys/kern/subr_param.c2
-rw-r--r--sys/kern/vfs_mount.c103
-rw-r--r--sys/mips/atheros/ar71xx_pci.c17
-rw-r--r--sys/mips/conf/OCTEON11
-rw-r--r--sys/net/if_pfsync.h26
-rw-r--r--sys/net/zlib.c9
-rw-r--r--sys/net/zlib.h2
-rw-r--r--sys/net80211/ieee80211_hostap.c16
-rw-r--r--sys/net80211/ieee80211_hwmp.c14
-rw-r--r--sys/net80211/ieee80211_radiotap.h13
-rw-r--r--sys/netinet/in.c11
-rw-r--r--sys/netinet6/in6.c9
-rw-r--r--sys/pc98/conf/GENERIC34
-rw-r--r--sys/powerpc/conf/GENERIC7
-rw-r--r--sys/powerpc/conf/GENERIC641
-rw-r--r--sys/sparc64/conf/GENERIC10
-rw-r--r--sys/sparc64/sparc64/interrupt.S9
-rw-r--r--sys/sys/mount.h23
66 files changed, 1104 insertions, 1288 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 7aff1e8..48f41b3 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -35,6 +35,7 @@ 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
@@ -317,15 +318,6 @@ device usb # USB Bus (required)
device ukbd # Keyboard
device umass # Disks/Mass storage - Requires scbus and da
-# FireWire support
-device firewire # FireWire bus code
-# sbp(4) works for some systems but causes boot failure on others
-#device sbp # SCSI over FireWire (Requires scbus and da)
-device fwe # Ethernet over FireWire (non-standard!)
-device fwip # IP over FireWire (RFC 2734,3146)
-device dcons # Dumb console driver
-device dcons_crom # Configuration ROM for dcons
-
# Sound support
device sound # Generic sound driver (required)
device snd_cmi # CMedia CMI8338/CMI8738
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index e358f96..a1b5a8f 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ptrace.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/uio.h>
@@ -162,8 +163,6 @@ const struct pmap_devmap *pmap_devmap_bootstrap_table;
uint32_t board_id;
struct arm_lbabi_tag *atag_list;
-uint32_t revision;
-uint64_t serial;
char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
char atags[LBABI_MAX_COMMAND_LINE * 2];
uint32_t memstart[LBABI_MAX_BANKS];
@@ -171,6 +170,31 @@ uint32_t memsize[LBABI_MAX_BANKS];
uint32_t membanks;
#endif
+static uint32_t board_revision;
+/* hex representation of uint64_t */
+static char board_serial[32];
+
+SYSCTL_NODE(_hw, OID_AUTO, board, CTLFLAG_RD, 0, "Board attributes");
+SYSCTL_UINT(_hw_board, OID_AUTO, revision, CTLFLAG_RD,
+ &board_revision, 0, "Board revision");
+SYSCTL_STRING(_hw_board, OID_AUTO, serial, CTLFLAG_RD,
+ board_serial, 0, "Board serial");
+
+void
+board_set_serial(uint64_t serial)
+{
+
+ snprintf(board_serial, sizeof(board_serial)-1,
+ "%016jx", serial);
+}
+
+void
+board_set_revision(uint32_t revision)
+{
+
+ board_revision = revision;
+}
+
void
sendsig(catcher, ksi, mask)
sig_t catcher;
@@ -849,6 +873,8 @@ vm_offset_t
linux_parse_boot_param(struct arm_boot_params *abp)
{
struct arm_lbabi_tag *walker;
+ uint32_t revision;
+ uint64_t serial;
/*
* Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2
@@ -883,9 +909,11 @@ linux_parse_boot_param(struct arm_boot_params *abp)
case ATAG_SERIAL:
serial = walker->u.tag_sn.low |
((uint64_t)walker->u.tag_sn.high << 32);
+ board_set_serial(serial);
break;
case ATAG_REVISION:
revision = walker->u.tag_rev.rev;
+ board_set_revision(revision);
break;
case ATAG_CMDLINE:
/* XXX open question: Parse this for boothowto? */
diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c
index a5af23c..4e78375 100644
--- a/sys/arm/arm/pl310.c
+++ b/sys/arm/arm/pl310.c
@@ -135,11 +135,12 @@ pl310_cache_sync(void)
return;
#ifdef PL310_ERRATA_753970
- /* Write uncached PL310 register */
- pl310_write4(pl310_softc, 0x740, 0xffffffff);
-#else
- pl310_write4(pl310_softc, PL310_CACHE_SYNC, 0xffffffff);
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ /* Write uncached PL310 register */
+ pl310_write4(pl310_softc, 0x740, 0xffffffff);
+ else
#endif
+ pl310_write4(pl310_softc, PL310_CACHE_SYNC, 0xffffffff);
}
@@ -152,13 +153,17 @@ pl310_wbinv_all(void)
PL310_LOCK(pl310_softc);
#ifdef PL310_ERRATA_727915
- platform_pl310_write_debug(pl310_softc, 3);
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r2p0 ||
+ pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ platform_pl310_write_debug(pl310_softc, 3);
#endif
pl310_write4(pl310_softc, PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
pl310_wait_background_op(PL310_CLEAN_INV_WAY, g_l2cache_way_mask);
pl310_cache_sync();
#ifdef PL310_ERRATA_727915
- platform_pl310_write_debug(pl310_softc, 0);
+ if (pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r2p0 ||
+ pl310_softc->sc_rtl_revision == CACHE_ID_RELEASE_r3p0)
+ platform_pl310_write_debug(pl310_softc, 0);
#endif
PL310_UNLOCK(pl310_softc);
}
@@ -186,18 +191,19 @@ pl310_wbinv_range(vm_paddr_t start, vm_size_t size)
#endif
while (size > 0) {
#ifdef PL310_ERRATA_588369
- /*
- * Errata 588369 says that clean + inv may keep the
- * cache line if it was clean, the recommanded workaround
- * is to clean then invalidate the cache line, with
- * write-back and cache linefill disabled
- */
-
- pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
- pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
-#else
- pl310_write4(pl310_softc, PL310_CLEAN_INV_LINE_PA, start);
+ if (pl310_softc->sc_rtl_revision <= CACHE_ID_RELEASE_r1p0) {
+ /*
+ * Errata 588369 says that clean + inv may keep the
+ * cache line if it was clean, the recommanded
+ * workaround is to clean then invalidate the cache
+ * line, with write-back and cache linefill disabled.
+ */
+ pl310_write4(pl310_softc, PL310_CLEAN_LINE_PA, start);
+ pl310_write4(pl310_softc, PL310_INV_LINE_PA, start);
+ } else
#endif
+ pl310_write4(pl310_softc, PL310_CLEAN_INV_LINE_PA,
+ start);
start += g_l2cache_line_size;
size -= g_l2cache_line_size;
}
@@ -307,6 +313,8 @@ pl310_attach(device_t dev)
pl310_filter, NULL, sc, &sc->sc_irq_h);
cache_id = pl310_read4(sc, PL310_CACHE_ID);
+ sc->sc_rtl_revision = (cache_id >> CACHE_ID_RELEASE_SHIFT) &
+ CACHE_ID_RELEASE_MASK;
device_printf(dev, "Part number: 0x%x, release: 0x%x\n",
(cache_id >> CACHE_ID_PARTNUM_SHIFT) & CACHE_ID_PARTNUM_MASK,
(cache_id >> CACHE_ID_RELEASE_SHIFT) & CACHE_ID_RELEASE_MASK);
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index 0df6281..d3e386d 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -193,6 +193,14 @@ int pmap_debug_level = 0;
#define PMAP_INLINE __inline
#endif /* PMAP_DEBUG */
+#ifdef ARM_L2_PIPT
+#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((pa), (size))
+#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((pa), (size))
+#else
+#define pmap_l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range((va), (size))
+#define pmap_l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range((va), (size))
+#endif
+
extern struct pv_addr systempage;
/*
@@ -786,11 +794,7 @@ pmap_l2ptp_ctor(void *mem, int size, void *arg, int flags)
pte = *ptep;
cpu_idcache_wbinv_range(va, PAGE_SIZE);
-#ifdef ARM_L2_PIPT
- cpu_l2cache_wbinv_range(pte & L2_S_FRAME, PAGE_SIZE);
-#else
- cpu_l2cache_wbinv_range(va, PAGE_SIZE);
-#endif
+ pmap_l2cache_wbinv_range(va, pte & L2_S_FRAME, PAGE_SIZE);
if ((pte & L2_S_CACHE_MASK) != pte_l2_s_cache_mode_pt) {
/*
* Page tables must have the cache-mode set to
@@ -2121,6 +2125,7 @@ pmap_kremove(vm_offset_t va)
cpu_tlb_flushD_SE(va);
cpu_cpwait();
*pte = 0;
+ PTE_SYNC(pte);
}
}
@@ -2387,11 +2392,7 @@ pmap_change_attr(vm_offset_t sva, vm_size_t len, int mode)
pte = *ptep &~ L2_S_CACHE_MASK;
cpu_idcache_wbinv_range(tmpva, PAGE_SIZE);
-#ifdef ARM_L2_PIPT
- cpu_l2cache_wbinv_range(pte & L2_S_FRAME, PAGE_SIZE);
-#else
- cpu_l2cache_wbinv_range(tmpva, PAGE_SIZE);
-#endif
+ pmap_l2cache_wbinv_range(tmpva, pte & L2_S_FRAME, PAGE_SIZE);
*ptep = pte;
cpu_tlb_flushID_SE(tmpva);
@@ -2754,6 +2755,9 @@ do_l2b_alloc:
else if (PV_BEEN_REFD(oflags))
cpu_tlb_flushD_SE(va);
}
+
+ if ((pmap != pmap_kernel()) && (pmap == &curproc->p_vmspace->vm_pmap))
+ cpu_icache_sync_range(va, PAGE_SIZE);
}
/*
@@ -3197,6 +3201,16 @@ pmap_zero_page_gen(vm_page_t pg, int off, int size)
else
bzero_page(cdstp);
+ /*
+ * Although aliasing is not possible if we use
+ * cdstp temporary mappings with memory that
+ * will be mapped later as non-cached or with write-through
+ * caches we might end up overwriting it when calling wbinv_all
+ * So make sure caches are clean after copy operation
+ */
+ cpu_idcache_wbinv_range(cdstp, size);
+ pmap_l2cache_wbinv_range(cdstp, phys, size);
+
mtx_unlock(&cmtx);
}
@@ -3276,12 +3290,23 @@ pmap_copy_page_generic(vm_paddr_t src, vm_paddr_t dst)
*cdst_pte = L2_S_PROTO | dst | pte_l2_s_cache_mode;
pmap_set_prot(cdst_pte, VM_PROT_READ | VM_PROT_WRITE, 0);
PTE_SYNC(cdst_pte);
+
cpu_tlb_flushD_SE(csrcp);
cpu_tlb_flushD_SE(cdstp);
cpu_cpwait();
+ /*
+ * Although aliasing is not possible if we use
+ * cdstp temporary mappings with memory that
+ * will be mapped later as non-cached or with write-through
+ * caches we might end up overwriting it when calling wbinv_all
+ * So make sure caches are clean after copy operation
+ */
bcopy_page(csrcp, cdstp);
+ cpu_idcache_wbinv_range(cdstp, PAGE_SIZE);
+ pmap_l2cache_wbinv_range(cdstp, dst, PAGE_SIZE);
+
mtx_unlock(&cmtx);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
index e8b2534..35343c8 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
@@ -891,7 +891,7 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+ (sc->depth/8) * (col + sc->xmargin);
fg = a & 0xf ;
- bg = (a >> 8) & 0xf;
+ bg = (a >> 4) & 0xf;
for (i = 0; i < BCMFB_FONT_HEIGHT; i++) {
for (j = 0, k = 7; j < 8; j++, k--) {
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
index 6baa8dd..7308c0f 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_machdep.c
@@ -78,6 +78,25 @@ initarm_gpio_init(void)
void
initarm_late_init(void)
{
+ phandle_t system;
+ pcell_t cells[2];
+ int len;
+
+ /*
+ * It seems there is no way to let syscons framework know
+ * that framebuffer resolution has changed. So just try
+ * to fetch data from FDT and go with defaults if failed
+ */
+ system = OF_finddevice("/system");
+ if (system != 0) {
+ len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
+ if (len > 0)
+ board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));
+
+ len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
+ if (len > 0)
+ board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
+ }
}
#define FDT_DEVMAP_MAX (2) // FIXME
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 2874dfd..1481d92 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -62,11 +62,11 @@ options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
# NFS support
#options NFSCL
-#options NFSSERVER #Network Filesystem Server
-#options NFSCLIENT #Network Filesystem Client
+#options NFSD
+#options NFSLOCKD
# Uncomment this for NFS root
-#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT #NFS usable as /, requires NFSCL
#options BOOTP_NFSROOT
#options BOOTP_COMPAT
#options BOOTP
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h
index 1a96176..4862453 100644
--- a/sys/arm/include/atomic.h
+++ b/sys/arm/include/atomic.h
@@ -47,9 +47,25 @@
#include <machine/cpuconf.h>
#endif
-#define mb()
-#define wmb()
-#define rmb()
+#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+#define isb() __asm __volatile("isb" : : : "memory")
+#define dsb() __asm __volatile("dsb" : : : "memory")
+#define dmb() __asm __volatile("dmb" : : : "memory")
+#elif defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) || \
+ defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6Z__) || \
+ defined (__ARM_ARCH_6ZK__)
+#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory")
+#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory")
+#define dmb() __asm __volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory")
+#else
+#define isb()
+#define dsb()
+#define dmb()
+#endif
+
+#define mb() dmb()
+#define wmb() dmb()
+#define rmb() dmb()
#ifndef I32_bit
#define I32_bit (1 << 7) /* IRQ disable */
diff --git a/sys/arm/include/machdep.h b/sys/arm/include/machdep.h
index 8ea5e2f..f50cde8 100644
--- a/sys/arm/include/machdep.h
+++ b/sys/arm/include/machdep.h
@@ -37,6 +37,10 @@ void initarm_gpio_init(void);
void initarm_late_init(void);
int platform_devmap_init(void);
+/* Board-specific attributes */
+void board_set_serial(uint64_t);
+void board_set_revision(uint32_t);
+
/* Needs to be initialised by platform_devmap_init */
extern const struct pmap_devmap *pmap_devmap_bootstrap_table;
diff --git a/sys/arm/include/pl310.h b/sys/arm/include/pl310.h
index 26f6c60..a3c42d8 100644
--- a/sys/arm/include/pl310.h
+++ b/sys/arm/include/pl310.h
@@ -131,6 +131,7 @@ struct pl310_softc {
void* sc_irq_h;
int sc_enabled;
struct mtx sc_mtx;
+ u_int sc_rtl_revision;
};
/**
diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h
index da4571d..4f7566e 100644
--- a/sys/arm/include/pmap.h
+++ b/sys/arm/include/pmap.h
@@ -61,7 +61,7 @@
#else
#define PTE_NOCACHE 1
#endif
-#define PTE_CACHE 4
+#define PTE_CACHE 6
#define PTE_DEVICE 2
#define PTE_PAGETABLE 4
#else
diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c
index 80cbe73..a47c131 100644
--- a/sys/arm/ti/cpsw/if_cpsw.c
+++ b/sys/arm/ti/cpsw/if_cpsw.c
@@ -98,7 +98,7 @@ static int cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
static int cpsw_init_slot_lists(struct cpsw_softc *sc);
static void cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot);
static void cpsw_fill_rx_queue_locked(struct cpsw_softc *sc);
-static void cpsw_watchdog(struct cpsw_softc *sc);
+static void cpsw_tx_watchdog(struct cpsw_softc *sc);
static void cpsw_intr_rx_thresh(void *arg);
static void cpsw_intr_rx(void *arg);
@@ -716,34 +716,24 @@ cpsw_start_locked(struct ifnet *ifp)
if (STAILQ_EMPTY(&newslots))
return;
- /* Attach new segments to the hardware TX queue. */
+ /* Attach the list of new buffers to the hardware TX queue. */
prev_slot = STAILQ_LAST(&sc->tx_active, cpsw_slot, next);
first_new_slot = STAILQ_FIRST(&newslots);
STAILQ_CONCAT(&sc->tx_active, &newslots);
if (prev_slot == NULL) {
/* Start the TX queue fresh. */
cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(first_new_slot->index));
+ cpsw_cpdma_txbd_paddr(first_new_slot->index));
} else {
- /* Add packets to current queue. */
- /* Race: The hardware might have sent the last packet
- * on the queue and stopped the transmitter just
- * before we got here. In that case, this is a no-op,
- * but it also means there's a TX interrupt waiting
- * to be processed as soon as we release the lock here.
- * That TX interrupt can detect and recover from this
- * situation; see cpsw_intr_tx_locked.
- */
+ /* Add buffers to end of current queue. */
cpsw_cpdma_write_txbd_next(prev_slot->index,
cpsw_cpdma_txbd_paddr(first_new_slot->index));
+ /* If underrun, restart queue. */
+ if (cpsw_cpdma_read_txbd_flags(prev_slot->index) & CPDMA_BD_EOQ)
+ cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
+ cpsw_cpdma_txbd_paddr(first_new_slot->index));
}
- /* If tx_retires hasn't changed, then we may have
- lost a TX interrupt, so let the timer tick. */
sc->tx_enqueues += enqueued;
- if (sc->tx_retires_at_wd_reset != sc->tx_retires) {
- sc->tx_retires_at_wd_reset = sc->tx_retires;
- sc->wd_timer = 5;
- }
sc->tx_queued += enqueued;
if (sc->tx_queued > sc->tx_max_queued) {
sc->tx_max_queued = sc->tx_queued;
@@ -771,7 +761,6 @@ cpsw_stop_locked(struct cpsw_softc *sc)
/* Stop tick engine */
callout_stop(&sc->wd_callout);
- sc->wd_timer = 0;
/* Wait for hardware to clear pending ops. */
CPSW_GLOBAL_UNLOCK(sc);
@@ -1098,14 +1087,10 @@ cpsw_fill_rx_queue_locked(struct cpsw_softc *sc)
cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
cpsw_cpdma_rxbd_paddr(next_slot->index));
} else {
- /* Extend an existing RX queue. */
+ /* Add buffers to end of current queue. */
cpsw_cpdma_write_rxbd_next(prev_slot->index,
cpsw_cpdma_rxbd_paddr(next_slot->index));
- /* XXX Order matters: Previous write must complete
- before next read begins in order to avoid an
- end-of-queue race. I think bus_write and bus_read have
- sufficient barriers built-in to ensure this. XXX */
- /* If old RX queue was stopped, restart it. */
+ /* If underrun, restart queue. */
if (cpsw_cpdma_read_rxbd_flags(prev_slot->index) & CPDMA_BD_EOQ) {
cpsw_write_4(CPSW_CPDMA_RX_HDP(0),
cpsw_cpdma_rxbd_paddr(next_slot->index));
@@ -1177,15 +1162,8 @@ cpsw_intr_tx_locked(void *arg)
/* Tell hardware the last item we dequeued. */
cpsw_write_4(CPSW_CPDMA_TX_CP(0),
cpsw_cpdma_txbd_paddr(last_slot->index));
- /* If transmitter stopped and there's more, restart it. */
- /* This resolves the race described in tx_start above. */
- if ((last_flags & CPDMA_BD_EOQ) && (slot != NULL)) {
- cpsw_write_4(CPSW_CPDMA_TX_HDP(0),
- cpsw_cpdma_txbd_paddr(slot->index));
- }
sc->tx_retires += retires;
sc->tx_queued -= retires;
- sc->wd_timer = 0;
}
}
@@ -1206,7 +1184,7 @@ cpsw_tick(void *msc)
struct cpsw_softc *sc = msc;
/* Check for TX timeout */
- cpsw_watchdog(sc);
+ cpsw_tx_watchdog(sc);
mii_tick(sc->mii);
@@ -1222,21 +1200,28 @@ cpsw_tick(void *msc)
}
static void
-cpsw_watchdog(struct cpsw_softc *sc)
+cpsw_tx_watchdog(struct cpsw_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet *ifp = sc->ifp;
- ifp = sc->ifp;
CPSW_GLOBAL_LOCK(sc);
- if (sc->wd_timer == 0 || --sc->wd_timer) {
- CPSW_GLOBAL_UNLOCK(sc);
- return;
+ if (sc->tx_retires > sc->tx_retires_at_last_tick) {
+ sc->tx_wd_timer = 0; /* Stuff got sent. */
+ } else if (sc->tx_queued == 0) {
+ sc->tx_wd_timer = 0; /* Nothing to send. */
+ } else {
+ /* There was something to send but we didn't. */
+ ++sc->tx_wd_timer;
+ if (sc->tx_wd_timer > 3) {
+ sc->tx_wd_timer = 0;
+ ifp->if_oerrors++;
+ if_printf(ifp, "watchdog timeout\n");
+ cpsw_stop_locked(sc);
+ cpsw_init_locked(sc);
+ CPSW_DEBUGF(("watchdog reset completed\n"));
+ }
}
-
- ifp->if_oerrors++;
- if_printf(ifp, "watchdog timeout\n");
- cpsw_stop_locked(sc);
- cpsw_init_locked(sc);
+ sc->tx_retires_at_last_tick = sc->tx_retires;
CPSW_GLOBAL_UNLOCK(sc);
}
@@ -1381,7 +1366,7 @@ cpsw_init_locked(void *arg)
/* Activate network interface */
sc->rx_running = 1;
sc->tx_running = 1;
- sc->wd_timer = 0;
+ sc->tx_wd_timer = 0;
callout_reset(&sc->wd_callout, hz, cpsw_tick, sc);
sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
diff --git a/sys/arm/ti/cpsw/if_cpswvar.h b/sys/arm/ti/cpsw/if_cpswvar.h
index 3cae489..35024c6 100644
--- a/sys/arm/ti/cpsw/if_cpswvar.h
+++ b/sys/arm/ti/cpsw/if_cpswvar.h
@@ -63,7 +63,7 @@ struct cpsw_softc {
int cpsw_media_status;
struct callout wd_callout;
- int wd_timer;
+ int tx_wd_timer;
bus_dma_tag_t mbuf_dtag;
@@ -82,7 +82,7 @@ struct cpsw_softc {
/* Statistics */
uint32_t tx_enqueues; /* total TX bufs added to queue */
uint32_t tx_retires; /* total TX bufs removed from queue */
- uint32_t tx_retires_at_wd_reset; /* used for watchdog */
+ uint32_t tx_retires_at_last_tick; /* used for watchdog */
/* Note: tx_queued != tx_enqueues - tx_retires
At driver reset, packets can be discarded
from TX queue without being retired. */
diff --git a/sys/arm/ti/ti_cpuid.c b/sys/arm/ti/ti_cpuid.c
index 16de8aa..89046c4 100644
--- a/sys/arm/ti/ti_cpuid.c
+++ b/sys/arm/ti/ti_cpuid.c
@@ -129,27 +129,75 @@ omap4_get_revision(void)
switch (hawkeye) {
case 0xB852:
- if (revision == 0)
+ switch (revision) {
+ case 0:
chip_revision = OMAP4430_REV_ES1_0;
- else
- chip_revision = OMAP4430_REV_ES2_0;
+ break;
+ case 1:
+ chip_revision = OMAP4430_REV_ES2_1;
+ break;
+ default:
+ chip_revision = OMAP4430_REV_UNKNOWN;
+ break;
+ }
break;
+
case 0xB95C:
- if (revision == 3)
+ switch (revision) {
+ case 3:
chip_revision = OMAP4430_REV_ES2_1;
- else if (revision == 4)
+ break;
+ case 4:
chip_revision = OMAP4430_REV_ES2_2;
- else
+ break;
+ case 6:
chip_revision = OMAP4430_REV_ES2_3;
+ break;
+ default:
+ chip_revision = OMAP4430_REV_UNKNOWN;
+ break;
+ }
break;
+
+ case 0xB94E:
+ switch (revision) {
+ case 0:
+ chip_revision = OMAP4460_REV_ES1_0;
+ break;
+ case 2:
+ chip_revision = OMAP4460_REV_ES1_1;
+ break;
+ default:
+ chip_revision = OMAP4460_REV_UNKNOWN;
+ break;
+ }
+ break;
+
+ case 0xB975:
+ switch (revision) {
+ case 0:
+ chip_revision = OMAP4470_REV_ES1_0;
+ break;
+ default:
+ chip_revision = OMAP4470_REV_UNKNOWN;
+ break;
+ }
+ break;
+
default:
/* Default to the latest revision if we can't determine type */
- chip_revision = OMAP4430_REV_ES2_3;
+ chip_revision = OMAP_UNKNOWN_DEV;
break;
}
- printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
- OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
- OMAP_REV_MINOR(chip_revision));
+ if (chip_revision != OMAP_UNKNOWN_DEV) {
+ printf("Texas Instruments OMAP%04x Processor, Revision ES%u.%u\n",
+ OMAP_REV_DEVICE(chip_revision), OMAP_REV_MAJOR(chip_revision),
+ OMAP_REV_MINOR(chip_revision));
+ }
+ else {
+ printf("Texas Instruments unknown OMAP chip: %04x, rev %d\n",
+ hawkeye, revision);
+ }
}
/**
diff --git a/sys/arm/ti/ti_cpuid.h b/sys/arm/ti/ti_cpuid.h
index f68f54c..6efbf32 100644
--- a/sys/arm/ti/ti_cpuid.h
+++ b/sys/arm/ti/ti_cpuid.h
@@ -30,34 +30,46 @@
#ifndef _TI_CPUID_H_
#define _TI_CPUID_H_
-#define OMAP_MAKEREV(d, a, b, c) \
+#define OMAP_MAKEREV(d, a, b, c) \
(uint32_t)(((d) << 16) | (((a) & 0xf) << 8) | (((b) & 0xf) << 4) | ((c) & 0xf))
-#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
-#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
-#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
-#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
+#define OMAP_REV_DEVICE(x) (((x) >> 16) & 0xffff)
+#define OMAP_REV_MAJOR(x) (((x) >> 8) & 0xf)
+#define OMAP_REV_MINOR(x) (((x) >> 4) & 0xf)
+#define OMAP_REV_MINOR_MINOR(x) (((x) >> 0) & 0xf)
#define OMAP3350_DEV 0x3530
-#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
-#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
-#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
-#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
-#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
-#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
+#define OMAP3350_REV_ES1_0 OMAP_MAKEREV(OMAP3350_DEV, 1, 0, 0)
+#define OMAP3530_REV_ES2_0 OMAP_MAKEREV(OMAP3350_DEV, 2, 0, 0)
+#define OMAP3530_REV_ES2_1 OMAP_MAKEREV(OMAP3350_DEV, 2, 1, 0)
+#define OMAP3530_REV_ES3_0 OMAP_MAKEREV(OMAP3350_DEV, 3, 0, 0)
+#define OMAP3530_REV_ES3_1 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 0)
+#define OMAP3530_REV_ES3_1_2 OMAP_MAKEREV(OMAP3350_DEV, 3, 1, 2)
#define OMAP4430_DEV 0x4430
-#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
-#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
-#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
-#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
-#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
+#define OMAP4430_REV_ES1_0 OMAP_MAKEREV(OMAP4430_DEV, 1, 0, 0)
+#define OMAP4430_REV_ES2_0 OMAP_MAKEREV(OMAP4430_DEV, 2, 0, 0)
+#define OMAP4430_REV_ES2_1 OMAP_MAKEREV(OMAP4430_DEV, 2, 1, 0)
+#define OMAP4430_REV_ES2_2 OMAP_MAKEREV(OMAP4430_DEV, 2, 2, 0)
+#define OMAP4430_REV_ES2_3 OMAP_MAKEREV(OMAP4430_DEV, 2, 3, 0)
+#define OMAP4430_REV_UNKNOWN OMAP_MAKEREV(OMAP4430_DEV, 9, 9, 9)
-#define AM335X_DEVREV(x) ((x) >> 28)
+#define OMAP4460_DEV 0x4460
+#define OMAP4460_REV_ES1_0 OMAP_MAKEREV(OMAP4460_DEV, 1, 0, 0)
+#define OMAP4460_REV_ES1_1 OMAP_MAKEREV(OMAP4460_DEV, 1, 1, 0)
+#define OMAP4460_REV_UNKNOWN OMAP_MAKEREV(OMAP4460_DEV, 9, 9, 9)
-#define CHIP_OMAP_3 0
-#define CHIP_OMAP_4 1
-#define CHIP_AM335X 2
+#define OMAP4470_DEV 0x4470
+#define OMAP4470_REV_ES1_0 OMAP_MAKEREV(OMAP4470_DEV, 1, 0, 0)
+#define OMAP4470_REV_UNKNOWN OMAP_MAKEREV(OMAP4470_DEV, 9, 9, 9)
+
+#define OMAP_UNKNOWN_DEV OMAP_MAKEREV(0x9999, 9, 9, 9)
+
+#define AM335X_DEVREV(x) ((x) >> 28)
+
+#define CHIP_OMAP_3 0
+#define CHIP_OMAP_4 1
+#define CHIP_AM335X 2
static __inline int ti_chip(void)
{
diff --git a/sys/arm/versatile/versatile_clcd.c b/sys/arm/versatile/versatile_clcd.c
index 53226ff..34d29fa 100644
--- a/sys/arm/versatile/versatile_clcd.c
+++ b/sys/arm/versatile/versatile_clcd.c
@@ -892,7 +892,7 @@ versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
+ (sc->depth/8) * (col + sc->xmargin);
fg = a & 0xf ;
- bg = (a >> 8) & 0xf;
+ bg = (a >> 4) & 0xf;
for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) {
for (j = 0, k = 7; j < 8; j++, k--) {
diff --git a/sys/boot/common/interp_forth.c b/sys/boot/common/interp_forth.c
index ef4265e..f89bc41 100644
--- a/sys/boot/common/interp_forth.c
+++ b/sys/boot/common/interp_forth.c
@@ -53,8 +53,8 @@ extern char bootprog_rev[];
/*
* FreeBSD loader default dictionary cells
*/
-#ifndef BF_DICTSIZE
-#define BF_DICTSIZE 10000
+#ifndef BF_DICTSIZE
+#define BF_DICTSIZE 10000
#endif
/*
@@ -247,6 +247,7 @@ bf_init(void)
char create_buf[41]; /* 31 characters-long builtins */
int fd;
+
bf_sys = ficlInitSystem(BF_DICTSIZE);
bf_vm = ficlNewVM(bf_sys);
diff --git a/sys/conf/options.mips b/sys/conf/options.mips
index a86a749..2f27206 100644
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -73,6 +73,7 @@ MAXMEM opt_global.h
#
OCTEON_MODEL opt_cvmx.h
OCTEON_VENDOR_LANNER opt_cvmx.h
+OCTEON_VENDOR_UBIQUITI opt_cvmx.h
OCTEON_VENDOR_RADISYS opt_cvmx.h
OCTEON_BOARD_CAPK_0100ND opt_cvmx.h
diff --git a/sys/contrib/octeon-sdk/cvmx-app-init.h b/sys/contrib/octeon-sdk/cvmx-app-init.h
index a986814..605f43e 100644
--- a/sys/contrib/octeon-sdk/cvmx-app-init.h
+++ b/sys/contrib/octeon-sdk/cvmx-app-init.h
@@ -299,6 +299,9 @@ enum cvmx_board_types_enum {
CVMX_BOARD_TYPE_CUST_LANNER_MR320= 20002,
CVMX_BOARD_TYPE_CUST_LANNER_MR321X=20007,
#endif
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ CVMX_BOARD_TYPE_CUST_UBIQUITI_E100=20002,
+#endif
#if defined(OCTEON_VENDOR_RADISYS)
CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE=20002,
#endif
@@ -426,6 +429,9 @@ static inline const char *cvmx_board_type_to_string(enum cvmx_board_types_enum t
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_LANNER_MR320)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_LANNER_MR321X)
#endif
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_UBIQUITI_E100)
+#endif
#if defined(OCTEON_VENDOR_RADISYS)
ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE)
#endif
diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c
index deb6018..8d2b0bd 100644
--- a/sys/contrib/octeon-sdk/cvmx-helper-board.c
+++ b/sys/contrib/octeon-sdk/cvmx-helper-board.c
@@ -592,6 +592,12 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return -1;
}
#endif
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100:
+ if (ipd_port > 2)
+ return -1;
+ return (7 - ipd_port);
+#endif
#if defined(OCTEON_VENDOR_RADISYS)
case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE:
/* No MII. */
@@ -1463,6 +1469,9 @@ cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void)
case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
#endif
+#if defined(OCTEON_VENDOR_UBIQUITI)
+ case CVMX_BOARD_TYPE_CUST_UBIQUITI_E100:
+#endif
#if defined(OCTEON_BOARD_CAPK_0100ND)
case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
#endif
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index 543ba43..78f19e2 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -423,7 +423,21 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
#ifdef AH_SUPPORT_AR5416
sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
- if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
+ if (rs->rs_status & HAL_RXERR_PHY) {
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ /*
+ * PHY error - make sure the channel flags
+ * reflect the actual channel configuration,
+ * not the received frame.
+ */
+ if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
+ sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
+ else if (IEEE80211_IS_CHAN_HT40D(ic->ic_curchan))
+ sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
+ else if (IEEE80211_IS_CHAN_HT20(ic->ic_curchan))
+ sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
+ } else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
struct ieee80211com *ic = ifp->if_l2com;
if ((rs->rs_flags & HAL_RX_2040) == 0)
@@ -435,6 +449,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
if ((rs->rs_flags & HAL_RX_GI) == 0)
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
}
+
#endif
sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf));
if (rs->rs_status & HAL_RXERR_CRC)
diff --git a/sys/dev/ath/if_ath_spectral.c b/sys/dev/ath/if_ath_spectral.c
index 12fb87a7..0dc0114 100644
--- a/sys/dev/ath/if_ath_spectral.c
+++ b/sys/dev/ath/if_ath_spectral.c
@@ -82,13 +82,20 @@ struct ath_spectral_state {
*/
/*
- * Attach DFS to the given interface
+ * Attach spectral to the given interface
*/
int
ath_spectral_attach(struct ath_softc *sc)
{
struct ath_spectral_state *ss;
+ /*
+ * If spectral isn't supported, don't error - just
+ * quietly complete.
+ */
+ if (! ath_hal_spectral_supported(sc->sc_ah))
+ return (0);
+
ss = malloc(sizeof(struct ath_spectral_state),
M_TEMP, M_WAITOK | M_ZERO);
@@ -106,11 +113,15 @@ ath_spectral_attach(struct ath_softc *sc)
}
/*
- * Detach DFS from the given interface
+ * Detach spectral from the given interface
*/
int
ath_spectral_detach(struct ath_softc *sc)
{
+
+ if (! ath_hal_spectral_supported(sc->sc_ah))
+ return (0);
+
if (sc->sc_spectral != NULL) {
free(sc->sc_spectral, M_TEMP);
}
@@ -148,6 +159,9 @@ ath_ioctl_spectral(struct ath_softc *sc, struct ath_diag *ad)
HAL_SPECTRAL_PARAM *pe;
struct ath_spectral_state *ss = sc->sc_spectral;
+ if (! ath_hal_spectral_supported(sc->sc_ah))
+ return (EINVAL);
+
if (ad->ad_id & ATH_DIAG_IN) {
/*
* Copy in data.
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 12252ed..2e170a3 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -1303,6 +1303,8 @@ void ath_intr(void *);
#define ath_hal_get_chan_ext_busy(_ah) \
((*(_ah)->ah_get11nExtBusy)((_ah)))
+#define ath_hal_spectral_supported(_ah) \
+ (ath_hal_getcapability(_ah, HAL_CAP_SPECTRAL_SCAN, 0, NULL) == HAL_OK)
#define ath_hal_spectral_get_config(_ah, _p) \
((*(_ah)->ah_spectralGetConfig)((_ah), (_p)))
#define ath_hal_spectral_configure(_ah, _p) \
diff --git a/sys/dev/nvme/nvme_test.c b/sys/dev/nvme/nvme_test.c
index 3d04ea5..4177227 100644
--- a/sys/dev/nvme/nvme_test.c
+++ b/sys/dev/nvme/nvme_test.c
@@ -287,10 +287,10 @@ nvme_ns_test(struct nvme_namespace *ns, u_long cmd, caddr_t arg)
for (i = 0; i < io_test->num_threads; i++)
#if __FreeBSD_version >= 800004
kthread_add(fn, io_test_internal,
- curproc, NULL, 0, 0, "nvme_io_test[%d]", i);
+ NULL, NULL, 0, 0, "nvme_io_test[%d]", i);
#else
kthread_create(fn, io_test_internal,
- curproc, 0, 0, "nvme_io_test[%d]", i);
+ NULL, 0, 0, "nvme_io_test[%d]", i);
#endif
tsleep(io_test_internal, 0, "nvme_test", io_test->time * 2 * hz);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 7290de6..7632e73 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -244,7 +244,7 @@ static const struct pci_quirk pci_quirks[] = {
* but support MSI just fine. QEMU uses the Intel 82440.
*/
{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 },
- { 0x12751275, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, /* BHyVe */
+ { 0x12751275, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, /* bhyve */
/*
* HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index f32e89a..c62f781 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -1440,26 +1440,37 @@ void
xhci_interrupt(struct xhci_softc *sc)
{
uint32_t status;
- uint32_t temp;
+ uint32_t iman;
USB_BUS_LOCK(&sc->sc_bus);
status = XREAD4(sc, oper, XHCI_USBSTS);
+ if (status == 0)
+ goto done;
/* acknowledge interrupts */
XWRITE4(sc, oper, XHCI_USBSTS, status);
- temp = XREAD4(sc, runt, XHCI_IMAN(0));
+ DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+
+ if (status & XHCI_STS_EINT) {
- /* acknowledge pending event */
+ /* acknowledge pending event */
+ iman = XREAD4(sc, runt, XHCI_IMAN(0));
- XWRITE4(sc, runt, XHCI_IMAN(0), temp);
+ /* reset interrupt */
+ XWRITE4(sc, runt, XHCI_IMAN(0), iman);
+
+ DPRINTFN(16, "real interrupt (iman=0x%08x)\n", iman);
+
+ /* check for event(s) */
+ xhci_interrupt_poll(sc);
+ }
- DPRINTFN(16, "real interrupt (sts=0x%08x, "
- "iman=0x%08x)\n", status, temp);
+ if (status & (XHCI_STS_PCD | XHCI_STS_HCH |
+ XHCI_STS_HSE | XHCI_STS_HCE)) {
- if (status != 0) {
if (status & XHCI_STS_PCD) {
xhci_root_intr(sc);
}
@@ -1479,9 +1490,7 @@ xhci_interrupt(struct xhci_softc *sc)
__FUNCTION__);
}
}
-
- xhci_interrupt_poll(sc);
-
+done:
USB_BUS_UNLOCK(&sc->sc_bus);
}
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index 3d2577f..3940636 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -2019,7 +2019,8 @@ run_key_set_cb(void *arg)
wcid = 0; /* NB: update WCID0 for group keys */
base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix);
} else {
- wcid = RUN_AID2WCID(associd);
+ wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
+ 1 : RUN_AID2WCID(associd);
base = RT2860_PKEY(wcid);
}
@@ -2374,9 +2375,12 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
struct run_softc *sc = ic->ic_ifp->if_softc;
uint8_t rate;
uint8_t ridx;
- uint8_t wcid = RUN_AID2WCID(ni->ni_associd);
+ uint8_t wcid;
int i, j;
+ wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
+ 1 : RUN_AID2WCID(ni->ni_associd);
+
if (wcid > RT2870_WCID_MAX) {
device_printf(sc->sc_dev, "wcid=%d out of range\n", wcid);
return;
@@ -3044,8 +3048,12 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
txd->flags = qflags;
txwi = (struct rt2860_txwi *)(txd + 1);
txwi->xflags = xflags;
- txwi->wcid = IEEE80211_IS_MULTICAST(wh->i_addr1) ?
- 0 : RUN_AID2WCID(ni->ni_associd);
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ txwi->wcid = 0;
+ } else {
+ txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
+ 1 : RUN_AID2WCID(ni->ni_associd);
+ }
/* clear leftover garbage bits */
txwi->flags = 0;
txwi->txop = 0;
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index 63ece1e..18f42bb 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -125,7 +125,6 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#endif
-
#include <geom/geom.h>
#include <machine/_inttypes.h>
@@ -145,8 +144,6 @@ __FBSDID("$FreeBSD$");
#include <xen/xenbus/xenbusvar.h>
-#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*(x)))
-
/*--------------------------- Forward Declarations --------------------------*/
/** Function signature for shutdown event handlers. */
typedef void (xctrl_shutdown_handler_t)(void);
@@ -165,7 +162,7 @@ struct xctrl_shutdown_reason {
};
/** Lookup table for shutdown event name to handler. */
-static struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = {
+static const struct xctrl_shutdown_reason xctrl_shutdown_reasons[] = {
{ "poweroff", xctrl_poweroff },
{ "reboot", xctrl_reboot },
{ "suspend", xctrl_suspend },
@@ -198,7 +195,6 @@ extern void xencons_resume(void);
static void
xctrl_suspend()
{
- u_int cpuid;
int i, j, k, fpp;
unsigned long max_pfn, start_info_mfn;
@@ -207,6 +203,8 @@ xctrl_suspend()
#ifdef SMP
struct thread *td;
cpuset_t map;
+ u_int cpuid;
+
/*
* Bind us to CPU 0 and stop any other VCPUs.
*/
@@ -231,7 +229,7 @@ xctrl_suspend()
mtx_lock(&Giant);
if (DEVICE_SUSPEND(root_bus) != 0) {
mtx_unlock(&Giant);
- printf("xen_suspend: device_suspend failed\n");
+ printf("%s: device_suspend failed\n", __func__);
#ifdef SMP
if (!CPU_EMPTY(&map))
restart_cpus(map);
@@ -343,9 +341,9 @@ xctrl_suspend()
* drivers need this.
*/
mtx_lock(&Giant);
- if (DEVICE_SUSPEND(root_bus)) {
+ if (DEVICE_SUSPEND(root_bus) != 0) {
mtx_unlock(&Giant);
- printf("xen_suspend: device_suspend failed\n");
+ printf("%s: device_suspend failed\n", __func__);
return;
}
mtx_unlock(&Giant);
@@ -396,8 +394,8 @@ xctrl_halt()
static void
xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
{
- struct xctrl_shutdown_reason *reason;
- struct xctrl_shutdown_reason *last_reason;
+ const struct xctrl_shutdown_reason *reason;
+ const struct xctrl_shutdown_reason *last_reason;
char *result;
int error;
int result_len;
@@ -408,7 +406,7 @@ xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
return;
reason = xctrl_shutdown_reasons;
- last_reason = reason + NUM_ELEMENTS(xctrl_shutdown_reasons);
+ last_reason = reason + nitems(xctrl_shutdown_reasons);
while (reason < last_reason) {
if (!strcmp(result, reason->name)) {
@@ -511,10 +509,10 @@ static device_method_t xctrl_methods[] = {
DEVMETHOD(device_attach, xctrl_attach),
DEVMETHOD(device_detach, xctrl_detach),
- { 0, 0 }
+ DEVMETHOD_END
};
DEFINE_CLASS_0(xctrl, xctrl_driver, xctrl_methods, sizeof(struct xctrl_softc));
devclass_t xctrl_devclass;
-DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, 0, 0);
+DRIVER_MODULE(xctrl, xenstore, xctrl_driver, xctrl_devclass, NULL, NULL);
diff --git a/sys/dev/xen/evtchn/evtchn_dev.c b/sys/dev/xen/evtchn/evtchn_dev.c
deleted file mode 100644
index 6925a22..0000000
--- a/sys/dev/xen/evtchn/evtchn_dev.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/******************************************************************************
- * evtchn.c
- *
- * Xenolinux driver for receiving and demuxing event-channel signals.
- *
- * Copyright (c) 2004, K A Fraser
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/uio.h>
-#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/selinfo.h>
-#include <sys/poll.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/ioccom.h>
-
-#include <machine/cpufunc.h>
-#include <machine/intr_machdep.h>
-#include <machine/xen-os.h>
-#include <xen/xen_intr.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-#include <machine/synch_bitops.h>
-
-#include <xen/hypervisor.h>
-
-
-typedef struct evtchn_sotfc {
-
- struct selinfo ev_rsel;
-} evtchn_softc_t;
-
-
-#ifdef linuxcrap
-/* NB. This must be shared amongst drivers if more things go in /dev/xen */
-static devfs_handle_t xen_dev_dir;
-#endif
-
-/* Only one process may open /dev/xen/evtchn at any time. */
-static unsigned long evtchn_dev_inuse;
-
-/* Notification ring, accessed via /dev/xen/evtchn. */
-
-#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
-
-#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
-static uint16_t *ring;
-static unsigned int ring_cons, ring_prod, ring_overflow;
-
-/* Which ports is user-space bound to? */
-static uint32_t bound_ports[32];
-
-/* Unique address for processes to sleep on */
-static void *evtchn_waddr = &ring;
-
-static struct mtx lock, upcall_lock;
-
-static d_read_t evtchn_read;
-static d_write_t evtchn_write;
-static d_ioctl_t evtchn_ioctl;
-static d_poll_t evtchn_poll;
-static d_open_t evtchn_open;
-static d_close_t evtchn_close;
-
-
-void
-evtchn_device_upcall(int port)
-{
- mtx_lock(&upcall_lock);
-
- mask_evtchn(port);
- clear_evtchn(port);
-
- if ( ring != NULL ) {
- if ( (ring_prod - ring_cons) < EVTCHN_RING_SIZE ) {
- ring[EVTCHN_RING_MASK(ring_prod)] = (uint16_t)port;
- if ( ring_cons == ring_prod++ ) {
- wakeup(evtchn_waddr);
- }
- }
- else {
- ring_overflow = 1;
- }
- }
-
- mtx_unlock(&upcall_lock);
-}
-
-static void
-__evtchn_reset_buffer_ring(void)
-{
- /* Initialise the ring to empty. Clear errors. */
- ring_cons = ring_prod = ring_overflow = 0;
-}
-
-static int
-evtchn_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
- int rc;
- unsigned int count, c, p, sst = 0, bytes1 = 0, bytes2 = 0;
- count = uio->uio_resid;
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 )
- {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- for ( ; ; ) {
- if ( (c = ring_cons) != (p = ring_prod) )
- break;
-
- if ( ring_overflow ) {
- rc = EFBIG;
- goto out;
- }
-
- if (sst != 0) {
- rc = EINTR;
- goto out;
- }
-
- /* PCATCH == check for signals before and after sleeping
- * PWAIT == priority of waiting on resource
- */
- sst = tsleep(evtchn_waddr, PWAIT|PCATCH, "evchwt", 10);
- }
-
- /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
- if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 ) {
- bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(uint16_t);
- bytes2 = EVTCHN_RING_MASK(p) * sizeof(uint16_t);
- }
- else {
- bytes1 = (p - c) * sizeof(uint16_t);
- bytes2 = 0;
- }
-
- /* Truncate chunks according to caller's maximum byte count. */
- if ( bytes1 > count ) {
- bytes1 = count;
- bytes2 = 0;
- }
- else if ( (bytes1 + bytes2) > count ) {
- bytes2 = count - bytes1;
- }
-
- if ( uiomove(&ring[EVTCHN_RING_MASK(c)], bytes1, uio) ||
- ((bytes2 != 0) && uiomove(&ring[0], bytes2, uio)))
- /* keeping this around as its replacement is not equivalent
- * copyout(&ring[0], &buf[bytes1], bytes2)
- */
- {
- rc = EFAULT;
- goto out;
- }
-
- ring_cons += (bytes1 + bytes2) / sizeof(uint16_t);
-
- rc = bytes1 + bytes2;
-
- out:
-
- return rc;
-}
-
-static int
-evtchn_write(struct cdev *dev, struct uio *uio, int ioflag)
-{
- int rc, i, count;
-
- count = uio->uio_resid;
-
- uint16_t *kbuf = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
-
-
- if ( kbuf == NULL )
- return ENOMEM;
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 ) {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- if ( uiomove(kbuf, count, uio) != 0 ) {
- rc = EFAULT;
- goto out;
- }
-
- mtx_lock_spin(&lock);
- for ( i = 0; i < (count/2); i++ )
- if ( test_bit(kbuf[i], &bound_ports[0]) )
- unmask_evtchn(kbuf[i]);
- mtx_unlock_spin(&lock);
-
- rc = count;
-
- out:
- free(kbuf, M_DEVBUF);
- return rc;
-}
-
-static int
-evtchn_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg,
- int mode, struct thread *td __unused)
-{
- int rc = 0;
-
- mtx_lock_spin(&lock);
-
- switch ( cmd )
- {
- case EVTCHN_RESET:
- __evtchn_reset_buffer_ring();
- break;
- case EVTCHN_BIND:
- if ( !synch_test_and_set_bit((int)arg, &bound_ports[0]) )
- unmask_evtchn((int)arg);
- else
- rc = EINVAL;
- break;
- case EVTCHN_UNBIND:
- if ( synch_test_and_clear_bit((int)arg, &bound_ports[0]) )
- mask_evtchn((int)arg);
- else
- rc = EINVAL;
- break;
- default:
- rc = ENOSYS;
- break;
- }
-
- mtx_unlock_spin(&lock);
-
- return rc;
-}
-
-static int
-evtchn_poll(struct cdev *dev, int poll_events, struct thread *td)
-{
-
- evtchn_softc_t *sc;
- unsigned int mask = POLLOUT | POLLWRNORM;
-
- sc = dev->si_drv1;
-
- if ( ring_cons != ring_prod )
- mask |= POLLIN | POLLRDNORM;
- else if ( ring_overflow )
- mask = POLLERR;
- else
- selrecord(td, &sc->ev_rsel);
-
-
- return mask;
-}
-
-
-static int
-evtchn_open(struct cdev *dev, int flag, int otyp, struct thread *td)
-{
- uint16_t *_ring;
-
- if (flag & O_NONBLOCK)
- return EBUSY;
-
- if ( synch_test_and_set_bit(0, &evtchn_dev_inuse) )
- return EBUSY;
-
- if ( (_ring = (uint16_t *)malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK)) == NULL )
- return ENOMEM;
-
- mtx_lock_spin(&lock);
- ring = _ring;
- __evtchn_reset_buffer_ring();
- mtx_unlock_spin(&lock);
-
-
- return 0;
-}
-
-static int
-evtchn_close(struct cdev *dev, int flag, int otyp, struct thread *td __unused)
-{
- int i;
-
- mtx_lock_spin(&lock);
- if (ring != NULL) {
- free(ring, M_DEVBUF);
- ring = NULL;
- }
- for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
- if ( synch_test_and_clear_bit(i, &bound_ports[0]) )
- mask_evtchn(i);
- mtx_unlock_spin(&lock);
-
- evtchn_dev_inuse = 0;
-
- return 0;
-}
-
-static struct cdevsw evtchn_devsw = {
- d_version: D_VERSION,
- d_open: evtchn_open,
- d_close: evtchn_close,
- d_read: evtchn_read,
- d_write: evtchn_write,
- d_ioctl: evtchn_ioctl,
- d_poll: evtchn_poll,
- d_name: "evtchn",
- d_flags: 0,
-};
-
-
-/* XXX - if this device is ever supposed to support use by more than one process
- * this global static will have to go away
- */
-static struct cdev *evtchn_dev;
-
-
-
-static int
-evtchn_init(void *dummy __unused)
-{
- /* XXX I believe we don't need these leaving them here for now until we
- * have some semblance of it working
- */
- mtx_init(&upcall_lock, "evtchup", NULL, MTX_DEF);
-
- /* (DEVFS) create '/dev/misc/evtchn'. */
- evtchn_dev = make_dev(&evtchn_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "xen/evtchn");
-
- mtx_init(&lock, "evch", NULL, MTX_SPIN | MTX_NOWITNESS);
-
- evtchn_dev->si_drv1 = malloc(sizeof(evtchn_softc_t), M_DEVBUF, M_WAITOK);
- bzero(evtchn_dev->si_drv1, sizeof(evtchn_softc_t));
-
- /* XXX I don't think we need any of this rubbish */
-#if 0
- if ( err != 0 )
- {
- printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
- return err;
- }
-
- /* (DEVFS) create directory '/dev/xen'. */
- xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
-
- /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
- pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
- &link_dest[3],
- sizeof(link_dest) - 3);
- if ( pos >= 0 )
- strncpy(&link_dest[pos], "../", 3);
- /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
- (void)devfs_mk_symlink(xen_dev_dir,
- "evtchn",
- DEVFS_FL_DEFAULT,
- &link_dest[pos],
- &symlink_handle,
- NULL);
-
- /* (DEVFS) automatically destroy the symlink with its destination. */
- devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
-#endif
- printk("Event-channel device installed.\n");
-
- return 0;
-}
-
-
-SYSINIT(evtchn_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, evtchn_init, NULL);
-
-
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 856c988..88641e3 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -208,8 +207,6 @@ struct xn_chain_data {
struct mbuf *xn_rx_chain[NET_RX_RING_SIZE+1];
};
-#define NUM_ELEMENTS(x) (sizeof(x)/sizeof(*x))
-
struct net_device_stats
{
u_long rx_packets; /* total packets received */
@@ -244,7 +241,6 @@ struct net_device_stats
};
struct netfront_info {
-
struct ifnet *xn_ifp;
#if __FreeBSD_version >= 700000
struct lro_ctrl xn_lro;
@@ -329,12 +325,6 @@ struct netfront_rx_info {
/* Access macros for acquiring freeing slots in xn_free_{tx,rx}_idxs[]. */
-
-
-/*
- * Access macros for acquiring freeing slots in tx_skbs[].
- */
-
static inline void
add_id_to_freelist(struct mbuf **list, uintptr_t id)
{
@@ -517,7 +507,6 @@ netfront_resume(device_t dev)
return (0);
}
-
/* Common code used when first setting up, and when resuming. */
static int
talk_to_backend(device_t dev, struct netfront_info *info)
@@ -605,7 +594,6 @@ talk_to_backend(device_t dev, struct netfront_info *info)
return err;
}
-
static int
setup_device(device_t dev, struct netfront_info *info)
{
@@ -794,7 +782,7 @@ netif_release_tx_bufs(struct netfront_info *np)
add_id_to_freelist(np->tx_mbufs, i);
np->xn_cdata.xn_tx_chain_cnt--;
if (np->xn_cdata.xn_tx_chain_cnt < 0) {
- panic("netif_release_tx_bufs: tx_chain_cnt must be >= 0");
+ panic("%s: tx_chain_cnt must be >= 0", __func__);
}
m_free(m);
}
@@ -946,7 +934,6 @@ refill:
reservation.domid = DOMID_SELF;
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-
/* After all PTEs have been zapped, flush the TLB. */
sc->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] =
UVMF_TLB_FLUSH|UVMF_ALL;
@@ -958,15 +945,11 @@ refill:
/* Zap PTEs and give away pages in one big multicall. */
(void)HYPERVISOR_multicall(sc->rx_mcl, i+1);
- /* Check return status of HYPERVISOR_dom_mem_op(). */
- if (unlikely(sc->rx_mcl[i].result != i))
- panic("Unable to reduce memory reservation\n");
- } else {
- if (HYPERVISOR_memory_op(
- XENMEM_decrease_reservation, &reservation)
- != i)
- panic("Unable to reduce memory "
- "reservation\n");
+ if (unlikely(sc->rx_mcl[i].result != i ||
+ HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+ &reservation) != i))
+ panic("%s: unable to reduce memory "
+ "reservation\n", __func__);
}
} else {
wmb();
@@ -1169,8 +1152,8 @@ xn_txeof(struct netfront_info *np)
ifp->if_opackets++;
if (unlikely(gnttab_query_foreign_access(
np->grant_tx_ref[id]) != 0)) {
- panic("grant id %u still in use by the backend",
- id);
+ panic("%s: grant id %u still in use by the "
+ "backend", __func__, id);
}
gnttab_end_foreign_access_ref(
np->grant_tx_ref[id]);
@@ -1210,7 +1193,6 @@ xn_txeof(struct netfront_info *np)
netif_wake_queue(dev);
#endif
}
-
}
static void
@@ -1240,7 +1222,6 @@ xn_intr(void *xsc)
xn_start(ifp);
}
-
static void
xennet_move_rx_slot(struct netfront_info *np, struct mbuf *m,
grant_ref_t ref)
@@ -1319,17 +1300,15 @@ xennet_get_responses(struct netfront_info *np,
m0 = m = m_prev = xennet_get_rx_mbuf(np, *cons);
-
if (rx->flags & NETRXF_extra_info) {
err = xennet_get_extras(np, extras, rp, cons);
}
-
if (m0 != NULL) {
m0->m_pkthdr.len = 0;
m0->m_next = NULL;
}
-
+
for (;;) {
u_long mfn;
@@ -1468,10 +1447,8 @@ xn_tick_locked(struct netfront_info *sc)
callout_reset(&sc->xn_stat_ch, hz, xn_tick, sc);
/* XXX placeholder for printing debug information */
-
}
-
static void
xn_tick(void *xsc)
{
@@ -1481,7 +1458,6 @@ xn_tick(void *xsc)
XN_RX_LOCK(sc);
xn_tick_locked(sc);
XN_RX_UNLOCK(sc);
-
}
/**
@@ -1595,10 +1571,12 @@ xn_assemble_tx_request(struct netfront_info *sc, struct mbuf *m_head)
tx = RING_GET_REQUEST(&sc->tx, sc->tx.req_prod_pvt);
id = get_id_from_freelist(sc->tx_mbufs);
if (id == 0)
- panic("xn_start_locked: was allocated the freelist head!\n");
+ panic("%s: was allocated the freelist head!\n",
+ __func__);
sc->xn_cdata.xn_tx_chain_cnt++;
if (sc->xn_cdata.xn_tx_chain_cnt > NET_TX_RING_SIZE)
- panic("xn_start_locked: tx_chain_cnt must be <= NET_TX_RING_SIZE\n");
+ panic("%s: tx_chain_cnt must be <= NET_TX_RING_SIZE\n",
+ __func__);
sc->tx_mbufs[id] = m;
tx->id = id;
ref = gnttab_claim_grant_reference(&sc->gref_tx_head);
@@ -1710,7 +1688,6 @@ xn_start_locked(struct ifnet *ifp)
}
}
-
static void
xn_start(struct ifnet *ifp)
{
@@ -1744,10 +1721,8 @@ xn_ifinit_locked(struct netfront_info *sc)
if_link_state_change(ifp, LINK_STATE_UP);
callout_reset(&sc->xn_stat_ch, hz, xn_tick, sc);
-
}
-
static void
xn_ifinit(void *xsc)
{
@@ -1756,10 +1731,8 @@ xn_ifinit(void *xsc)
XN_LOCK(sc);
xn_ifinit_locked(sc);
XN_UNLOCK(sc);
-
}
-
static int
xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -2261,7 +2234,7 @@ static device_method_t netfront_methods[] = {
/* Xenbus interface */
DEVMETHOD(xenbus_otherend_changed, netfront_backend_changed),
- { 0, 0 }
+ DEVMETHOD_END
};
static driver_t netfront_driver = {
@@ -2271,4 +2244,5 @@ static driver_t netfront_driver = {
};
devclass_t netfront_devclass;
-DRIVER_MODULE(xe, xenbusb_front, netfront_driver, netfront_devclass, 0, 0);
+DRIVER_MODULE(xe, xenbusb_front, netfront_driver, netfront_devclass, NULL,
+ NULL);
diff --git a/sys/dev/xen/xenpci/machine_reboot.c b/sys/dev/xen/xenpci/machine_reboot.c
deleted file mode 100644
index 4036554..0000000
--- a/sys/dev/xen/xenpci/machine_reboot.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * Copyright (c) 2008 Citrix Systems, Inc.
- * 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/bus.h>
-#include <sys/kernel.h>
-#include <sys/interrupt.h>
-
-#include <machine/atomic.h>
-#include <machine/xen/xen-os.h>
-#include <xen/hypervisor.h>
-#include <xen/xen_intr.h>
-
-#include <dev/xen/xenpci/xenpcivar.h>
-
-void
-xen_suspend()
-{
- int suspend_cancelled;
-
- if (DEVICE_SUSPEND(root_bus)) {
- printf("xen_suspend: device_suspend failed\n");
- return;
- }
-
- /*
- * Make sure we don't change cpus or switch to some other
- * thread. for the duration.
- */
- critical_enter();
-
- /*
- * Prevent any races with evtchn_interrupt() handler.
- */
- irq_suspend();
- disable_intr();
-
- suspend_cancelled = HYPERVISOR_suspend(0);
- if (!suspend_cancelled)
- xenpci_resume();
-
- /*
- * Re-enable interrupts and put the scheduler back to normal.
- */
- enable_intr();
- critical_exit();
-
- /*
- * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or
- * similar.
- */
- if (!suspend_cancelled)
- DEVICE_RESUME(root_bus);
-}
diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h
index 9a87fc4..7d97bb8 100755
--- a/sys/fs/ext2fs/ext2_dinode.h
+++ b/sys/fs/ext2fs/ext2_dinode.h
@@ -29,8 +29,6 @@
#ifndef _FS_EXT2FS_EXT2_DINODE_H_
#define _FS_EXT2FS_EXT2_DINODE_H_
-#define e2di_size_high e2di_dacl
-
/*
* Special inode numbers
* The root inode is the root of the file system. Inode 0 can't be used for
@@ -87,11 +85,11 @@
struct ext2fs_dinode {
uint16_t e2di_mode; /* 0: IFMT, permissions; see below. */
uint16_t e2di_uid; /* 2: Owner UID */
- uint32_t e2di_size; /* 4: Size (in bytes) */
- uint32_t e2di_atime; /* 8: Access time */
- uint32_t e2di_ctime; /* 12: Change time */
- uint32_t e2di_mtime; /* 16: Modification time */
- uint32_t e2di_dtime; /* 20: Deletion time */
+ uint32_t e2di_size; /* 4: Size (in bytes) */
+ uint32_t e2di_atime; /* 8: Access time */
+ uint32_t e2di_ctime; /* 12: Change time */
+ uint32_t e2di_mtime; /* 16: Modification time */
+ uint32_t e2di_dtime; /* 20: Deletion time */
uint16_t e2di_gid; /* 24: Owner GID */
uint16_t e2di_nlink; /* 26: File link count */
uint32_t e2di_nblock; /* 28: Blocks count */
@@ -99,22 +97,23 @@ struct ext2fs_dinode {
uint32_t e2di_version; /* 36: Low 32 bits inode version */
uint32_t e2di_blocks[EXT2_N_BLOCKS]; /* 40: disk blocks */
uint32_t e2di_gen; /* 100: generation number */
- uint32_t e2di_facl; /* 104: file ACL (not implemented) */
- uint32_t e2di_dacl; /* 108: dir ACL (not implemented) */
- uint32_t e2di_faddr; /* 112: fragment address */
+ uint32_t e2di_facl; /* 104: Low EA block */
+ uint32_t e2di_size_high; /* 108: Upper bits of file size */
+ uint32_t e2di_faddr; /* 112: Fragment address (obsolete) */
uint16_t e2di_nblock_high; /* 116: Blocks count bits 47:32 */
- uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 */
+ uint16_t e2di_facl_high; /* 118: File EA bits 47:32 */
uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits */
uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits */
- uint32_t e2di_linux_reserved3; /* 124 */
- uint16_t e2di_extra_isize;
- uint16_t e2di_pad1;
- uint32_t e2di_ctime_extra; /* Extra change time */
- uint32_t e2di_mtime_extra; /* Extra modification time */
- uint32_t e2di_atime_extra; /* Extra access time */
- uint32_t e2di_crtime; /* Creation (birth)time */
- uint32_t e2di_crtime_extra; /* Extra creation (birth)time */
- uint32_t e2di_version_hi; /* High 30 bits of inode version */
+ uint16_t e2di_chksum_lo; /* 124: Lower inode checksum */
+ uint16_t e2di_lx_reserved; /* 126: Unused */
+ uint16_t e2di_extra_isize; /* 128: Size of this inode */
+ uint16_t e2di_chksum_hi; /* 130: High inode checksum */
+ uint32_t e2di_ctime_extra; /* 132: Extra change time */
+ uint32_t e2di_mtime_extra; /* 136: Extra modification time */
+ uint32_t e2di_atime_extra; /* 140: Extra access time */
+ uint32_t e2di_crtime; /* 144: Creation (birth)time */
+ uint32_t e2di_crtime_extra; /* 148: Extra creation (birth)time */
+ uint32_t e2di_version_hi; /* 152: High bits of inode version */
};
#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */
diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c
index 5b71a6b..e576568 100644
--- a/sys/fs/fuse/fuse_io.c
+++ b/sys/fs/fuse/fuse_io.c
@@ -113,7 +113,7 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh);
static int
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
- struct ucred *cred, struct fuse_filehandle *fufh);
+ struct ucred *cred, struct fuse_filehandle *fufh, int ioflag);
int
fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
@@ -162,7 +162,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
} else {
FS_DEBUG("buffered write of vnode %ju\n",
(uintmax_t)VTOILLU(vp));
- err = fuse_write_biobackend(vp, uio, cred, fufh);
+ err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag);
}
break;
default:
@@ -371,7 +371,7 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio,
static int
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
- struct ucred *cred, struct fuse_filehandle *fufh)
+ struct ucred *cred, struct fuse_filehandle *fufh, int ioflag)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct buf *bp;
@@ -390,6 +390,8 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio,
return (EINVAL);
if (uio->uio_resid == 0)
return (0);
+ if (ioflag & IO_APPEND)
+ uio_setoffset(uio, fvdat->filesize);
/*
* Find all of this file's B_NEEDCOMMIT buffers. If our writes
diff --git a/sys/fs/nandfs/nandfs_segment.c b/sys/fs/nandfs/nandfs_segment.c
index 836bead..7433e77 100644
--- a/sys/fs/nandfs/nandfs_segment.c
+++ b/sys/fs/nandfs/nandfs_segment.c
@@ -478,39 +478,19 @@ nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
struct nandfs_node *nandfs_node;
struct vnode *vp, *mvp;
struct thread *td;
- int error, lockreq, update;
+ int error, update;
td = curthread;
- lockreq = LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY;
- MNT_ILOCK(mp);
-
- MNT_VNODE_FOREACH(vp, mp, mvp) {
+ MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
update = 0;
- if (mp->mnt_syncer == vp)
- continue;
- if (VOP_ISLOCKED(vp))
- continue;
-
- VI_LOCK(vp);
- MNT_IUNLOCK(mp);
- if (vp->v_iflag & VI_DOOMED) {
+ if (mp->mnt_syncer == vp || VOP_ISLOCKED(vp)) {
VI_UNLOCK(vp);
- MNT_ILOCK(mp);
- continue;
- }
-
- if ((error = vget(vp, lockreq, td)) != 0) {
- MNT_ILOCK(mp);
continue;
}
-
- if (vp->v_iflag & VI_DOOMED) {
- vput(vp);
- MNT_ILOCK(mp);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_NOWAIT, td) != 0)
continue;
- }
nandfs_node = VTON(vp);
if (nandfs_node->nn_flags & IN_MODIFIED) {
@@ -532,12 +512,8 @@ nandfs_iterate_dirty_vnodes(struct mount *mp, struct nandfs_seginfo *seginfo)
if (update)
nandfs_node_update(nandfs_node);
-
- MNT_ILOCK(mp);
}
- MNT_IUNLOCK(mp);
-
return (0);
}
diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h
index 0878e55..4f37020 100644
--- a/sys/fs/nullfs/null.h
+++ b/sys/fs/nullfs/null.h
@@ -34,9 +34,15 @@
* $FreeBSD$
*/
+#ifndef FS_NULL_H
+#define FS_NULL_H
+
+#define NULLM_CACHE 0x0001
+
struct null_mount {
struct mount *nullm_vfs;
struct vnode *nullm_rootvp; /* Reference to root null_node */
+ uint64_t nullm_flags;
};
#ifdef _KERNEL
@@ -80,3 +86,5 @@ MALLOC_DECLARE(M_NULLFSNODE);
#endif /* NULLFS_DEBUG */
#endif /* _KERNEL */
+
+#endif
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index b2c7a75..0b72249 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -224,6 +224,9 @@ null_nodeget(mp, lowervp, vpp)
* provide ready to use vnode.
*/
if (VOP_ISLOCKED(lowervp) != LK_EXCLUSIVE) {
+ KASSERT((MOUNTTONULLMOUNT(mp)->nullm_flags & NULLM_CACHE) != 0,
+ ("lowervp %p is not excl locked and cache is disabled",
+ lowervp));
vn_lock(lowervp, LK_UPGRADE | LK_RETRY);
if ((lowervp->v_iflag & VI_DOOMED) != 0) {
vput(lowervp);
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 7d84d51..5abfa49 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -67,6 +67,15 @@ static vfs_vget_t nullfs_vget;
static vfs_extattrctl_t nullfs_extattrctl;
static vfs_reclaim_lowervp_t nullfs_reclaim_lowervp;
+/* Mount options that we support. */
+static const char *nullfs_opts[] = {
+ "cache",
+ "export",
+ "from",
+ "target",
+ NULL
+};
+
/*
* Mount null layer
*/
@@ -86,9 +95,11 @@ nullfs_mount(struct mount *mp)
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_NULLFS))
return (EPERM);
-
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
+ if (vfs_filteropt(mp->mnt_optnew, nullfs_opts))
+ return (EINVAL);
+
/*
* Update is a no-op
*/
@@ -149,7 +160,7 @@ nullfs_mount(struct mount *mp)
}
xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
- M_NULLFSMNT, M_WAITOK);
+ M_NULLFSMNT, M_WAITOK | M_ZERO);
/*
* Save reference to underlying FS
@@ -187,16 +198,27 @@ nullfs_mount(struct mount *mp)
mp->mnt_flag |= MNT_LOCAL;
MNT_IUNLOCK(mp);
}
+
+ xmp->nullm_flags |= NULLM_CACHE;
+ if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0)
+ xmp->nullm_flags &= ~NULLM_CACHE;
+
MNT_ILOCK(mp);
- mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
- (MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED);
+ if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
+ mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
+ (MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED |
+ MNTK_EXTENDED_SHARED);
+ }
mp->mnt_kern_flag |= MNTK_LOOKUP_EXCL_DOTDOT;
MNT_IUNLOCK(mp);
mp->mnt_data = xmp;
vfs_getnewfsid(mp);
- MNT_ILOCK(xmp->nullm_vfs);
- TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp, mnt_upper_link);
- MNT_IUNLOCK(xmp->nullm_vfs);
+ if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
+ MNT_ILOCK(xmp->nullm_vfs);
+ TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp,
+ mnt_upper_link);
+ MNT_IUNLOCK(xmp->nullm_vfs);
+ }
vfs_mountedfrom(mp, target);
@@ -234,13 +256,15 @@ nullfs_unmount(mp, mntflags)
*/
mntdata = mp->mnt_data;
ump = mntdata->nullm_vfs;
- MNT_ILOCK(ump);
- while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
- ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
- msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
+ if ((mntdata->nullm_flags & NULLM_CACHE) != 0) {
+ MNT_ILOCK(ump);
+ while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
+ ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
+ msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
+ }
+ TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
+ MNT_IUNLOCK(ump);
}
- TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
- MNT_IUNLOCK(ump);
mp->mnt_data = NULL;
free(mntdata, M_NULLFSMNT);
return (0);
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index f530ed2..cc35d81 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -692,7 +692,22 @@ null_unlock(struct vop_unlock_args *ap)
static int
null_inactive(struct vop_inactive_args *ap __unused)
{
+ struct vnode *vp;
+ struct mount *mp;
+ struct null_mount *xmp;
+ vp = ap->a_vp;
+ mp = vp->v_mount;
+ xmp = MOUNTTONULLMOUNT(mp);
+ if ((xmp->nullm_flags & NULLM_CACHE) == 0) {
+ /*
+ * If this is the last reference and caching of the
+ * nullfs vnodes is not enabled, then free up the
+ * vnode so as not to tie up the lower vnodes.
+ */
+ vp->v_object = NULL;
+ vrecycle(vp);
+ }
return (0);
}
diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
index 1c6d714..8073c64 100644
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -49,6 +49,7 @@
/* --------------------------------------------------------------------- */
#include <sys/malloc.h>
#include <sys/systm.h>
+#include <sys/tree.h>
#include <sys/vmmeter.h>
#include <vm/swap_pager.h>
@@ -60,104 +61,81 @@ MALLOC_DECLARE(M_TMPFSNAME);
/*
* Internal representation of a tmpfs directory entry.
*/
+
+LIST_HEAD(tmpfs_dir_duphead, tmpfs_dirent);
+
struct tmpfs_dirent {
- TAILQ_ENTRY(tmpfs_dirent) td_entries;
+ /*
+ * Depending on td_cookie flag entry can be of 3 types:
+ * - regular -- no hash collisions, stored in RB-Tree
+ * - duphead -- synthetic linked list head for dup entries
+ * - dup -- stored in linked list instead of RB-Tree
+ */
+ union {
+ /* regular and duphead entry types */
+ RB_ENTRY(tmpfs_dirent) td_entries;
- /* Length of the name stored in this directory entry. This avoids
- * the need to recalculate it every time the name is used. */
- uint16_t td_namelen;
+ /* dup entry type */
+ struct {
+ LIST_ENTRY(tmpfs_dirent) entries;
+ LIST_ENTRY(tmpfs_dirent) index_entries;
+ } td_dup;
+ } uh;
- /* The name of the entry, allocated from a string pool. This
- * string is not required to be zero-terminated; therefore, the
- * td_namelen field must always be used when accessing its value. */
- char * td_name;
+ uint32_t td_cookie;
+ uint32_t td_hash;
+ u_int td_namelen;
/* Pointer to the node this entry refers to. In case this field
* is NULL, the node is a whiteout. */
struct tmpfs_node * td_node;
+
+ union {
+ /*
+ * The name of the entry, allocated from a string pool. This
+ * string is not required to be zero-terminated.
+ */
+ char * td_name; /* regular, dup */
+ struct tmpfs_dir_duphead td_duphead; /* duphead */
+ } ud;
};
-/* A directory in tmpfs holds a sorted list of directory entries, which in
+/* A directory in tmpfs holds a list of directory entries, which in
* turn point to other files (which can be directories themselves).
*
- * In tmpfs, this list is managed by a tail queue, whose head is defined by
+ * In tmpfs, this list is managed by a RB-Tree, whose head is defined by
* the struct tmpfs_dir type.
*
- * It is imporant to notice that directories do not have entries for . and
+ * It is important to notice that directories do not have entries for . and
* .. as other file systems do. These can be generated when requested
* based on information available by other means, such as the pointer to
* the node itself in the former case or the pointer to the parent directory
* in the latter case. This is done to simplify tmpfs's code and, more
* importantly, to remove redundancy. */
-TAILQ_HEAD(tmpfs_dir, tmpfs_dirent);
+RB_HEAD(tmpfs_dir, tmpfs_dirent);
/* Each entry in a directory has a cookie that identifies it. Cookies
* supersede offsets within directories because, given how tmpfs stores
- * directories in memory, there is no such thing as an offset. (Emulating
- * a real offset could be very difficult.)
- *
+ * directories in memory, there is no such thing as an offset.
+ *
* The '.', '..' and the end of directory markers have fixed cookies which
* cannot collide with the cookies generated by other entries. The cookies
- * fot the other entries are generated based on the memory address on which
- * stores their information is stored.
- *
- * Ideally, using the entry's memory pointer as the cookie would be enough
- * to represent it and it wouldn't cause collisions in any system.
- * Unfortunately, this results in "offsets" with very large values which
- * later raise problems in the Linux compatibility layer (and maybe in other
- * places) as described in PR kern/32034. Hence we need to workaround this
- * with a rather ugly hack.
- *
- * Linux 32-bit binaries, unless built with _FILE_OFFSET_BITS=64, have off_t
- * set to 'long', which is a 32-bit *signed* long integer. Regardless of
- * the macro value, GLIBC (2.3 at least) always uses the getdents64
- * system call (when calling readdir) which internally returns off64_t
- * offsets. In order to make 32-bit binaries work, *GLIBC* converts the
- * 64-bit values returned by the kernel to 32-bit ones and aborts with
- * EOVERFLOW if the conversion results in values that won't fit in 32-bit
- * integers (which it assumes is because the directory is extremely large).
- * This wouldn't cause problems if we were dealing with unsigned integers,
- * but as we have signed integers, this check fails due to sign expansion.
+ * for the other entries are generated based on the file name hash value or
+ * unique number in case of name hash collision.
*
- * For example, consider that the kernel returns the 0xc1234567 cookie to
- * userspace in a off64_t integer. Later on, GLIBC casts this value to
- * off_t (remember, signed) with code similar to:
- * system call returns the offset in kernel_value;
- * off_t casted_value = kernel_value;
- * if (sizeof(off_t) != sizeof(off64_t) &&
- * kernel_value != casted_value)
- * error!
- * In this case, casted_value still has 0xc1234567, but when it is compared
- * for equality against kernel_value, it is promoted to a 64-bit integer and
- * becomes 0xffffffffc1234567, which is different than 0x00000000c1234567.
- * Then, GLIBC assumes this is because the directory is very large.
- *
- * Given that all the above happens in user-space, we have no control over
- * it; therefore we must workaround the issue here. We do this by
- * truncating the pointer value to a 32-bit integer and hope that there
- * won't be collisions. In fact, this will not cause any problems in
- * 32-bit platforms but some might arise in 64-bit machines (I'm not sure
- * if they can happen at all in practice).
- *
- * XXX A nicer solution shall be attempted. */
-#ifdef _KERNEL
-#define TMPFS_DIRCOOKIE_DOT 0
-#define TMPFS_DIRCOOKIE_DOTDOT 1
-#define TMPFS_DIRCOOKIE_EOF 2
-static __inline
-off_t
-tmpfs_dircookie(struct tmpfs_dirent *de)
-{
- off_t cookie;
-
- cookie = ((off_t)(uintptr_t)de >> 1) & 0x7FFFFFFF;
- MPASS(cookie != TMPFS_DIRCOOKIE_DOT);
- MPASS(cookie != TMPFS_DIRCOOKIE_DOTDOT);
- MPASS(cookie != TMPFS_DIRCOOKIE_EOF);
+ * To preserve compatibility cookies are limited to 31 bits.
+ */
- return cookie;
-}
-#endif
+#define TMPFS_DIRCOOKIE_DOT 0
+#define TMPFS_DIRCOOKIE_DOTDOT 1
+#define TMPFS_DIRCOOKIE_EOF 2
+#define TMPFS_DIRCOOKIE_MASK ((off_t)0x3fffffffU)
+#define TMPFS_DIRCOOKIE_MIN ((off_t)0x00000004U)
+#define TMPFS_DIRCOOKIE_DUP ((off_t)0x40000000U)
+#define TMPFS_DIRCOOKIE_DUPHEAD ((off_t)0x80000000U)
+#define TMPFS_DIRCOOKIE_DUP_MIN TMPFS_DIRCOOKIE_DUP
+#define TMPFS_DIRCOOKIE_DUP_MAX \
+ (TMPFS_DIRCOOKIE_DUP | TMPFS_DIRCOOKIE_MASK)
/* --------------------------------------------------------------------- */
@@ -243,29 +221,31 @@ struct tmpfs_node {
dev_t tn_rdev;
/* Valid when tn_type == VDIR. */
- struct tn_dir{
+ struct tn_dir {
/* Pointer to the parent directory. The root
* directory has a pointer to itself in this field;
* this property identifies the root node. */
struct tmpfs_node * tn_parent;
- /* Head of a tail-queue that links the contents of
- * the directory together. See above for a
- * description of its contents. */
+ /* Head of a tree that links the contents of
+ * the directory together. */
struct tmpfs_dir tn_dirhead;
+ /* Head of a list the contains fake directory entries
+ * heads, i.e. entries with TMPFS_DIRCOOKIE_DUPHEAD
+ * flag. */
+ struct tmpfs_dir_duphead tn_dupindex;
+
/* Number and pointer of the first directory entry
* returned by the readdir operation if it were
* called again to continue reading data from the
* same directory as before. This is used to speed
* up reads of long directories, assuming that no
* more than one read is in progress at a given time.
- * Otherwise, these values are discarded and a linear
- * scan is performed from the beginning up to the
- * point where readdir starts returning values. */
+ * Otherwise, these values are discarded. */
off_t tn_readdir_lastn;
struct tmpfs_dirent * tn_readdir_lastp;
- }tn_dir;
+ } tn_dir;
/* Valid when tn_type == VLNK. */
/* The link's target, allocated from a string pool. */
@@ -419,9 +399,9 @@ int tmpfs_alloc_node(struct tmpfs_mount *, enum vtype,
char *, dev_t, struct tmpfs_node **);
void tmpfs_free_node(struct tmpfs_mount *, struct tmpfs_node *);
int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
- const char *, uint16_t, struct tmpfs_dirent **);
-void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *,
- boolean_t);
+ const char *, u_int, struct tmpfs_dirent **);
+void tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
+void tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
int tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
struct vnode **);
void tmpfs_free_vp(struct vnode *);
@@ -429,13 +409,12 @@ int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
struct componentname *, char *);
void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
+void tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
struct tmpfs_node *f,
struct componentname *cnp);
-int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
-int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *);
-struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
-int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
+int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, int,
+ u_long *, int *);
int tmpfs_dir_whiteout_add(struct vnode *, struct componentname *);
void tmpfs_dir_whiteout_remove(struct vnode *, struct componentname *);
int tmpfs_reg_resize(struct vnode *, off_t, boolean_t);
@@ -467,8 +446,8 @@ int tmpfs_truncate(struct vnode *, off_t);
* with a length of 'len'.
*/
#define TMPFS_DIRENT_MATCHES(de, name, len) \
- (de->td_namelen == (uint16_t)len && \
- bcmp((de)->td_name, (name), (de)->td_namelen) == 0)
+ (de->td_namelen == len && \
+ bcmp((de)->ud.td_name, (name), (de)->td_namelen) == 0)
/* --------------------------------------------------------------------- */
@@ -476,11 +455,10 @@ int tmpfs_truncate(struct vnode *, off_t);
* Ensures that the node pointed by 'node' is a directory and that its
* contents are consistent with respect to directories.
*/
-#define TMPFS_VALIDATE_DIR(node) \
- MPASS((node)->tn_type == VDIR); \
- MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
- MPASS((node)->tn_dir.tn_readdir_lastp == NULL || \
- tmpfs_dircookie((node)->tn_dir.tn_readdir_lastp) == (node)->tn_dir.tn_readdir_lastn);
+#define TMPFS_VALIDATE_DIR(node) do { \
+ MPASS((node)->tn_type == VDIR); \
+ MPASS((node)->tn_size % sizeof(struct tmpfs_dirent) == 0); \
+} while (0)
/* --------------------------------------------------------------------- */
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 5f1616c..47ac2e6 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -37,6 +37,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/fnv_hash.h>
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
@@ -58,6 +59,11 @@ __FBSDID("$FreeBSD$");
#include <fs/tmpfs/tmpfs_fifoops.h>
#include <fs/tmpfs/tmpfs_vnops.h>
+struct tmpfs_dir_cursor {
+ struct tmpfs_dirent *tdc_current;
+ struct tmpfs_dirent *tdc_tree;
+};
+
SYSCTL_NODE(_vfs, OID_AUTO, tmpfs, CTLFLAG_RW, 0, "tmpfs file system");
static long tmpfs_pages_reserved = TMPFS_PAGES_MINRESERVED;
@@ -87,6 +93,10 @@ SYSCTL_PROC(_vfs_tmpfs, OID_AUTO, memory_reserved, CTLTYPE_LONG|CTLFLAG_RW,
&tmpfs_pages_reserved, 0, sysctl_mem_reserved, "L",
"Amount of available memory and swap below which tmpfs growth stops");
+static __inline int tmpfs_dirtree_cmp(struct tmpfs_dirent *a,
+ struct tmpfs_dirent *b);
+RB_PROTOTYPE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp);
+
size_t
tmpfs_mem_avail(void)
{
@@ -188,7 +198,8 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type,
break;
case VDIR:
- TAILQ_INIT(&nnode->tn_dir.tn_dirhead);
+ RB_INIT(&nnode->tn_dir.tn_dirhead);
+ LIST_INIT(&nnode->tn_dir.tn_dupindex);
MPASS(parent != nnode);
MPASS(IMPLIES(parent == NULL, tmp->tm_root == NULL));
nnode->tn_dir.tn_parent = (parent == NULL) ? nnode : parent;
@@ -309,6 +320,49 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
/* --------------------------------------------------------------------- */
+static __inline uint32_t
+tmpfs_dirent_hash(const char *name, u_int len)
+{
+ uint32_t hash;
+
+ hash = fnv_32_buf(name, len, FNV1_32_INIT + len) & TMPFS_DIRCOOKIE_MASK;
+#ifdef TMPFS_DEBUG_DIRCOOKIE_DUP
+ hash &= 0xf;
+#endif
+ if (hash < TMPFS_DIRCOOKIE_MIN)
+ hash += TMPFS_DIRCOOKIE_MIN;
+
+ return (hash);
+}
+
+static __inline off_t
+tmpfs_dirent_cookie(struct tmpfs_dirent *de)
+{
+ MPASS(de->td_cookie >= TMPFS_DIRCOOKIE_MIN);
+
+ return (de->td_cookie);
+}
+
+static __inline boolean_t
+tmpfs_dirent_dup(struct tmpfs_dirent *de)
+{
+ return ((de->td_cookie & TMPFS_DIRCOOKIE_DUP) != 0);
+}
+
+static __inline boolean_t
+tmpfs_dirent_duphead(struct tmpfs_dirent *de)
+{
+ return ((de->td_cookie & TMPFS_DIRCOOKIE_DUPHEAD) != 0);
+}
+
+void
+tmpfs_dirent_init(struct tmpfs_dirent *de, const char *name, u_int namelen)
+{
+ de->td_hash = de->td_cookie = tmpfs_dirent_hash(name, namelen);
+ memcpy(de->ud.td_name, name, namelen);
+ de->td_namelen = namelen;
+}
+
/*
* Allocates a new directory entry for the node node with a name of name.
* The new directory entry is returned in *de.
@@ -320,17 +374,17 @@ tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
*/
int
tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node,
- const char *name, uint16_t len, struct tmpfs_dirent **de)
+ const char *name, u_int len, struct tmpfs_dirent **de)
{
struct tmpfs_dirent *nde;
- nde = (struct tmpfs_dirent *)uma_zalloc(
- tmp->tm_dirent_pool, M_WAITOK);
- nde->td_name = malloc(len, M_TMPFSNAME, M_WAITOK);
- nde->td_namelen = len;
- memcpy(nde->td_name, name, len);
-
+ nde = uma_zalloc(tmp->tm_dirent_pool, M_WAITOK);
nde->td_node = node;
+ if (name != NULL) {
+ nde->ud.td_name = malloc(len, M_TMPFSNAME, M_WAITOK);
+ tmpfs_dirent_init(nde, name, len);
+ } else
+ nde->td_namelen = 0;
if (node != NULL)
node->tn_links++;
@@ -351,20 +405,17 @@ tmpfs_alloc_dirent(struct tmpfs_mount *tmp, struct tmpfs_node *node,
* directory entry, as it may already have been released from the outside.
*/
void
-tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de,
- boolean_t node_exists)
+tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de)
{
- if (node_exists) {
- struct tmpfs_node *node;
+ struct tmpfs_node *node;
- node = de->td_node;
- if (node != NULL) {
- MPASS(node->tn_links > 0);
- node->tn_links--;
- }
+ node = de->td_node;
+ if (node != NULL) {
+ MPASS(node->tn_links > 0);
+ node->tn_links--;
}
-
- free(de->td_name, M_TMPFSNAME);
+ if (!tmpfs_dirent_duphead(de) && de->ud.td_name != NULL)
+ free(de->ud.td_name, M_TMPFSNAME);
uma_zfree(tmp->tm_dirent_pool, de);
}
@@ -586,7 +637,7 @@ tmpfs_alloc_file(struct vnode *dvp, struct vnode **vpp, struct vattr *vap,
/* Allocate a vnode for the new file. */
error = tmpfs_alloc_vp(dvp->v_mount, node, LK_EXCLUSIVE, vpp);
if (error != 0) {
- tmpfs_free_dirent(tmp, de, TRUE);
+ tmpfs_free_dirent(tmp, de);
tmpfs_free_node(tmp, node);
goto out;
}
@@ -605,6 +656,215 @@ out:
/* --------------------------------------------------------------------- */
+static struct tmpfs_dirent *
+tmpfs_dir_first(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc)
+{
+ struct tmpfs_dirent *de;
+
+ de = RB_MIN(tmpfs_dir, &dnode->tn_dir.tn_dirhead);
+ dc->tdc_tree = de;
+ if (de != NULL && tmpfs_dirent_duphead(de))
+ de = LIST_FIRST(&de->ud.td_duphead);
+ dc->tdc_current = de;
+
+ return (dc->tdc_current);
+}
+
+static struct tmpfs_dirent *
+tmpfs_dir_next(struct tmpfs_node *dnode, struct tmpfs_dir_cursor *dc)
+{
+ struct tmpfs_dirent *de;
+
+ MPASS(dc->tdc_tree != NULL);
+ if (tmpfs_dirent_dup(dc->tdc_current)) {
+ dc->tdc_current = LIST_NEXT(dc->tdc_current, uh.td_dup.entries);
+ if (dc->tdc_current != NULL)
+ return (dc->tdc_current);
+ }
+ dc->tdc_tree = dc->tdc_current = RB_NEXT(tmpfs_dir,
+ &dnode->tn_dir.tn_dirhead, dc->tdc_tree);
+ if ((de = dc->tdc_current) != NULL && tmpfs_dirent_duphead(de)) {
+ dc->tdc_current = LIST_FIRST(&de->ud.td_duphead);
+ MPASS(dc->tdc_current != NULL);
+ }
+
+ return (dc->tdc_current);
+}
+
+/* Lookup directory entry in RB-Tree. Function may return duphead entry. */
+static struct tmpfs_dirent *
+tmpfs_dir_xlookup_hash(struct tmpfs_node *dnode, uint32_t hash)
+{
+ struct tmpfs_dirent *de, dekey;
+
+ dekey.td_hash = hash;
+ de = RB_FIND(tmpfs_dir, &dnode->tn_dir.tn_dirhead, &dekey);
+ return (de);
+}
+
+/* Lookup directory entry by cookie, initialize directory cursor accordingly. */
+static struct tmpfs_dirent *
+tmpfs_dir_lookup_cookie(struct tmpfs_node *node, off_t cookie,
+ struct tmpfs_dir_cursor *dc)
+{
+ struct tmpfs_dir *dirhead = &node->tn_dir.tn_dirhead;
+ struct tmpfs_dirent *de, dekey;
+
+ MPASS(cookie >= TMPFS_DIRCOOKIE_MIN);
+
+ if (cookie == node->tn_dir.tn_readdir_lastn &&
+ (de = node->tn_dir.tn_readdir_lastp) != NULL) {
+ /* Protect against possible race, tn_readdir_last[pn]
+ * may be updated with only shared vnode lock held. */
+ if (cookie == tmpfs_dirent_cookie(de))
+ goto out;
+ }
+
+ if ((cookie & TMPFS_DIRCOOKIE_DUP) != 0) {
+ LIST_FOREACH(de, &node->tn_dir.tn_dupindex,
+ uh.td_dup.index_entries) {
+ MPASS(tmpfs_dirent_dup(de));
+ if (de->td_cookie == cookie)
+ goto out;
+ /* dupindex list is sorted. */
+ if (de->td_cookie < cookie) {
+ de = NULL;
+ goto out;
+ }
+ }
+ MPASS(de == NULL);
+ goto out;
+ }
+
+ MPASS((cookie & TMPFS_DIRCOOKIE_MASK) == cookie);
+ dekey.td_hash = cookie;
+ /* Recover if direntry for cookie was removed */
+ de = RB_NFIND(tmpfs_dir, dirhead, &dekey);
+ dc->tdc_tree = de;
+ dc->tdc_current = de;
+ if (de != NULL && tmpfs_dirent_duphead(de)) {
+ dc->tdc_current = LIST_FIRST(&de->ud.td_duphead);
+ MPASS(dc->tdc_current != NULL);
+ }
+ return (dc->tdc_current);
+
+out:
+ dc->tdc_tree = de;
+ dc->tdc_current = de;
+ if (de != NULL && tmpfs_dirent_dup(de))
+ dc->tdc_tree = tmpfs_dir_xlookup_hash(node,
+ de->td_hash);
+ return (dc->tdc_current);
+}
+
+/*
+ * Looks for a directory entry in the directory represented by node.
+ * 'cnp' describes the name of the entry to look for. Note that the .
+ * and .. components are not allowed as they do not physically exist
+ * within directories.
+ *
+ * Returns a pointer to the entry when found, otherwise NULL.
+ */
+struct tmpfs_dirent *
+tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
+ struct componentname *cnp)
+{
+ struct tmpfs_dir_duphead *duphead;
+ struct tmpfs_dirent *de;
+ uint32_t hash;
+
+ MPASS(IMPLIES(cnp->cn_namelen == 1, cnp->cn_nameptr[0] != '.'));
+ MPASS(IMPLIES(cnp->cn_namelen == 2, !(cnp->cn_nameptr[0] == '.' &&
+ cnp->cn_nameptr[1] == '.')));
+ TMPFS_VALIDATE_DIR(node);
+
+ hash = tmpfs_dirent_hash(cnp->cn_nameptr, cnp->cn_namelen);
+ de = tmpfs_dir_xlookup_hash(node, hash);
+ if (de != NULL && tmpfs_dirent_duphead(de)) {
+ duphead = &de->ud.td_duphead;
+ LIST_FOREACH(de, duphead, uh.td_dup.entries) {
+ if (TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr,
+ cnp->cn_namelen))
+ break;
+ }
+ } else if (de != NULL) {
+ if (!TMPFS_DIRENT_MATCHES(de, cnp->cn_nameptr,
+ cnp->cn_namelen))
+ de = NULL;
+ }
+ if (de != NULL && f != NULL && de->td_node != f)
+ de = NULL;
+
+ return (de);
+}
+
+/*
+ * Attach duplicate-cookie directory entry nde to dnode and insert to dupindex
+ * list, allocate new cookie value.
+ */
+static void
+tmpfs_dir_attach_dup(struct tmpfs_node *dnode,
+ struct tmpfs_dir_duphead *duphead, struct tmpfs_dirent *nde)
+{
+ struct tmpfs_dir_duphead *dupindex;
+ struct tmpfs_dirent *de, *pde;
+
+ dupindex = &dnode->tn_dir.tn_dupindex;
+ de = LIST_FIRST(dupindex);
+ if (de == NULL || de->td_cookie < TMPFS_DIRCOOKIE_DUP_MAX) {
+ if (de == NULL)
+ nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN;
+ else
+ nde->td_cookie = de->td_cookie + 1;
+ MPASS(tmpfs_dirent_dup(nde));
+ LIST_INSERT_HEAD(dupindex, nde, uh.td_dup.index_entries);
+ LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
+ return;
+ }
+
+ /*
+ * Cookie numbers are near exhaustion. Scan dupindex list for unused
+ * numbers. dupindex list is sorted in descending order. Keep it so
+ * after inserting nde.
+ */
+ while (1) {
+ pde = de;
+ de = LIST_NEXT(de, uh.td_dup.index_entries);
+ if (de == NULL && pde->td_cookie != TMPFS_DIRCOOKIE_DUP_MIN) {
+ /*
+ * Last element of the index doesn't have minimal cookie
+ * value, use it.
+ */
+ nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MIN;
+ LIST_INSERT_AFTER(pde, nde, uh.td_dup.index_entries);
+ LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
+ return;
+ } else if (de == NULL) {
+ /*
+ * We are so lucky have 2^30 hash duplicates in single
+ * directory :) Return largest possible cookie value.
+ * It should be fine except possible issues with
+ * VOP_READDIR restart.
+ */
+ nde->td_cookie = TMPFS_DIRCOOKIE_DUP_MAX;
+ LIST_INSERT_HEAD(dupindex, nde,
+ uh.td_dup.index_entries);
+ LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
+ return;
+ }
+ if (de->td_cookie + 1 == pde->td_cookie ||
+ de->td_cookie >= TMPFS_DIRCOOKIE_DUP_MAX)
+ continue; /* No hole or invalid cookie. */
+ nde->td_cookie = de->td_cookie + 1;
+ MPASS(tmpfs_dirent_dup(nde));
+ MPASS(pde->td_cookie > nde->td_cookie);
+ MPASS(nde->td_cookie > de->td_cookie);
+ LIST_INSERT_BEFORE(de, nde, uh.td_dup.index_entries);
+ LIST_INSERT_HEAD(duphead, nde, uh.td_dup.entries);
+ return;
+ };
+}
+
/*
* Attaches the directory entry de to the directory represented by vp.
* Note that this does not change the link count of the node pointed by
@@ -614,10 +874,38 @@ void
tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de)
{
struct tmpfs_node *dnode;
+ struct tmpfs_dirent *xde, *nde;
ASSERT_VOP_ELOCKED(vp, __func__);
+ MPASS(de->td_namelen > 0);
+ MPASS(de->td_hash >= TMPFS_DIRCOOKIE_MIN);
+ MPASS(de->td_cookie == de->td_hash);
+
dnode = VP_TO_TMPFS_DIR(vp);
- TAILQ_INSERT_TAIL(&dnode->tn_dir.tn_dirhead, de, td_entries);
+ dnode->tn_dir.tn_readdir_lastn = 0;
+ dnode->tn_dir.tn_readdir_lastp = NULL;
+
+ MPASS(!tmpfs_dirent_dup(de));
+ xde = RB_INSERT(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de);
+ if (xde != NULL && tmpfs_dirent_duphead(xde))
+ tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de);
+ else if (xde != NULL) {
+ /*
+ * Allocate new duphead. Swap xde with duphead to avoid
+ * adding/removing elements with the same hash.
+ */
+ MPASS(!tmpfs_dirent_dup(xde));
+ tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), NULL, NULL, 0,
+ &nde);
+ /* *nde = *xde; XXX gcc 4.2.1 may generate invalid code. */
+ memcpy(nde, xde, sizeof(*xde));
+ xde->td_cookie |= TMPFS_DIRCOOKIE_DUPHEAD;
+ LIST_INIT(&xde->ud.td_duphead);
+ xde->td_namelen = 0;
+ xde->td_node = NULL;
+ tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, nde);
+ tmpfs_dir_attach_dup(dnode, &xde->ud.td_duphead, de);
+ }
dnode->tn_size += sizeof(struct tmpfs_dirent);
dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
TMPFS_NODE_MODIFIED;
@@ -633,58 +921,61 @@ tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de)
void
tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de)
{
+ struct tmpfs_mount *tmp;
+ struct tmpfs_dir *head;
struct tmpfs_node *dnode;
+ struct tmpfs_dirent *xde;
ASSERT_VOP_ELOCKED(vp, __func__);
- dnode = VP_TO_TMPFS_DIR(vp);
- if (dnode->tn_dir.tn_readdir_lastp == de) {
- dnode->tn_dir.tn_readdir_lastn = 0;
- dnode->tn_dir.tn_readdir_lastp = NULL;
- }
+ dnode = VP_TO_TMPFS_DIR(vp);
+ head = &dnode->tn_dir.tn_dirhead;
+ dnode->tn_dir.tn_readdir_lastn = 0;
+ dnode->tn_dir.tn_readdir_lastp = NULL;
+
+ if (tmpfs_dirent_dup(de)) {
+ /* Remove duphead if de was last entry. */
+ if (LIST_NEXT(de, uh.td_dup.entries) == NULL) {
+ xde = tmpfs_dir_xlookup_hash(dnode, de->td_hash);
+ MPASS(tmpfs_dirent_duphead(xde));
+ } else
+ xde = NULL;
+ LIST_REMOVE(de, uh.td_dup.entries);
+ LIST_REMOVE(de, uh.td_dup.index_entries);
+ if (xde != NULL) {
+ if (LIST_EMPTY(&xde->ud.td_duphead)) {
+ RB_REMOVE(tmpfs_dir, head, xde);
+ tmp = VFS_TO_TMPFS(vp->v_mount);
+ MPASS(xde->td_node == NULL);
+ tmpfs_free_dirent(tmp, xde);
+ }
+ }
+ } else
+ RB_REMOVE(tmpfs_dir, head, de);
- TAILQ_REMOVE(&dnode->tn_dir.tn_dirhead, de, td_entries);
dnode->tn_size -= sizeof(struct tmpfs_dirent);
dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
TMPFS_NODE_MODIFIED;
}
-/* --------------------------------------------------------------------- */
-
-/*
- * Looks for a directory entry in the directory represented by node.
- * 'cnp' describes the name of the entry to look for. Note that the .
- * and .. components are not allowed as they do not physically exist
- * within directories.
- *
- * Returns a pointer to the entry when found, otherwise NULL.
- */
-struct tmpfs_dirent *
-tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
- struct componentname *cnp)
+void
+tmpfs_dir_destroy(struct tmpfs_mount *tmp, struct tmpfs_node *dnode)
{
- boolean_t found;
- struct tmpfs_dirent *de;
-
- MPASS(IMPLIES(cnp->cn_namelen == 1, cnp->cn_nameptr[0] != '.'));
- MPASS(IMPLIES(cnp->cn_namelen == 2, !(cnp->cn_nameptr[0] == '.' &&
- cnp->cn_nameptr[1] == '.')));
- TMPFS_VALIDATE_DIR(node);
-
- found = 0;
- TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) {
- if (f != NULL && de->td_node != f)
- continue;
- MPASS(cnp->cn_namelen < 0xffff);
- if (de->td_namelen == (uint16_t)cnp->cn_namelen &&
- bcmp(de->td_name, cnp->cn_nameptr, de->td_namelen) == 0) {
- found = 1;
- break;
+ struct tmpfs_dirent *de, *dde, *nde;
+
+ RB_FOREACH_SAFE(de, tmpfs_dir, &dnode->tn_dir.tn_dirhead, nde) {
+ RB_REMOVE(tmpfs_dir, &dnode->tn_dir.tn_dirhead, de);
+ /* Node may already be destroyed. */
+ de->td_node = NULL;
+ if (tmpfs_dirent_duphead(de)) {
+ while ((dde = LIST_FIRST(&de->ud.td_duphead)) != NULL) {
+ LIST_REMOVE(dde, uh.td_dup.entries);
+ dde->td_node = NULL;
+ tmpfs_free_dirent(tmp, dde);
+ }
}
+ tmpfs_free_dirent(tmp, de);
}
- node->tn_status |= TMPFS_NODE_ACCESSED;
-
- return found ? de : NULL;
}
/* --------------------------------------------------------------------- */
@@ -696,7 +987,7 @@ tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f,
* hold the directory entry or an appropriate error code if another
* error happens.
*/
-int
+static int
tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
{
int error;
@@ -713,12 +1004,9 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
dent.d_reclen = GENERIC_DIRSIZ(&dent);
if (dent.d_reclen > uio->uio_resid)
- error = -1;
- else {
+ error = EJUSTRETURN;
+ else
error = uiomove(&dent, dent.d_reclen, uio);
- if (error == 0)
- uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
- }
node->tn_status |= TMPFS_NODE_ACCESSED;
@@ -734,7 +1022,7 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio)
* hold the directory entry or an appropriate error code if another
* error happens.
*/
-int
+static int
tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
{
int error;
@@ -763,19 +1051,9 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
dent.d_reclen = GENERIC_DIRSIZ(&dent);
if (dent.d_reclen > uio->uio_resid)
- error = -1;
- else {
+ error = EJUSTRETURN;
+ else
error = uiomove(&dent, dent.d_reclen, uio);
- if (error == 0) {
- struct tmpfs_dirent *de;
-
- de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
- if (de == NULL)
- uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
- else
- uio->uio_offset = tmpfs_dircookie(de);
- }
- }
node->tn_status |= TMPFS_NODE_ACCESSED;
@@ -785,30 +1063,6 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
/* --------------------------------------------------------------------- */
/*
- * Lookup a directory entry by its associated cookie.
- */
-struct tmpfs_dirent *
-tmpfs_dir_lookupbycookie(struct tmpfs_node *node, off_t cookie)
-{
- struct tmpfs_dirent *de;
-
- if (cookie == node->tn_dir.tn_readdir_lastn &&
- node->tn_dir.tn_readdir_lastp != NULL) {
- return node->tn_dir.tn_readdir_lastp;
- }
-
- TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) {
- if (tmpfs_dircookie(de) == cookie) {
- break;
- }
- }
-
- return de;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
* Helper function for tmpfs_readdir. Returns as much directory entries
* as can fit in the uio space. The read starts at uio->uio_offset.
* The function returns 0 on success, -1 if there was not enough space
@@ -816,27 +1070,47 @@ tmpfs_dir_lookupbycookie(struct tmpfs_node *node, off_t cookie)
* error code if another error happens.
*/
int
-tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
+tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int cnt,
+ u_long *cookies, int *ncookies)
{
- int error;
- off_t startcookie;
+ struct tmpfs_dir_cursor dc;
struct tmpfs_dirent *de;
+ off_t off;
+ int error;
TMPFS_VALIDATE_DIR(node);
- /* Locate the first directory entry we have to return. We have cached
- * the last readdir in the node, so use those values if appropriate.
- * Otherwise do a linear scan to find the requested entry. */
- startcookie = uio->uio_offset;
- MPASS(startcookie != TMPFS_DIRCOOKIE_DOT);
- MPASS(startcookie != TMPFS_DIRCOOKIE_DOTDOT);
- if (startcookie == TMPFS_DIRCOOKIE_EOF) {
- return 0;
- } else {
- de = tmpfs_dir_lookupbycookie(node, startcookie);
- }
- if (de == NULL) {
- return EINVAL;
+ off = 0;
+ switch (uio->uio_offset) {
+ case TMPFS_DIRCOOKIE_DOT:
+ error = tmpfs_dir_getdotdent(node, uio);
+ if (error != 0)
+ return (error);
+ uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT;
+ if (cnt != 0)
+ cookies[(*ncookies)++] = off = uio->uio_offset;
+ case TMPFS_DIRCOOKIE_DOTDOT:
+ error = tmpfs_dir_getdotdotdent(node, uio);
+ if (error != 0)
+ return (error);
+ de = tmpfs_dir_first(node, &dc);
+ if (de == NULL)
+ uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
+ else
+ uio->uio_offset = tmpfs_dirent_cookie(de);
+ if (cnt != 0)
+ cookies[(*ncookies)++] = off = uio->uio_offset;
+ if (de == NULL)
+ return (0);
+ break;
+ case TMPFS_DIRCOOKIE_EOF:
+ return (0);
+ default:
+ de = tmpfs_dir_lookup_cookie(node, uio->uio_offset, &dc);
+ if (de == NULL)
+ return (EINVAL);
+ if (cnt != 0)
+ off = tmpfs_dirent_cookie(de);
}
/* Read as much entries as possible; i.e., until we reach the end of
@@ -887,14 +1161,14 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
}
d.d_namlen = de->td_namelen;
MPASS(de->td_namelen < sizeof(d.d_name));
- (void)memcpy(d.d_name, de->td_name, de->td_namelen);
+ (void)memcpy(d.d_name, de->ud.td_name, de->td_namelen);
d.d_name[de->td_namelen] = '\0';
d.d_reclen = GENERIC_DIRSIZ(&d);
/* Stop reading if the directory entry we are treating is
* bigger than the amount of data that can be returned. */
if (d.d_reclen > uio->uio_resid) {
- error = -1;
+ error = EJUSTRETURN;
break;
}
@@ -902,21 +1176,30 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, off_t *cntp)
* advance pointers. */
error = uiomove(&d, d.d_reclen, uio);
if (error == 0) {
- (*cntp)++;
- de = TAILQ_NEXT(de, td_entries);
+ de = tmpfs_dir_next(node, &dc);
+ if (cnt != 0) {
+ if (de == NULL)
+ off = TMPFS_DIRCOOKIE_EOF;
+ else
+ off = tmpfs_dirent_cookie(de);
+ MPASS(*ncookies < cnt);
+ cookies[(*ncookies)++] = off;
+ }
}
} while (error == 0 && uio->uio_resid > 0 && de != NULL);
/* Update the offset and cache. */
- if (de == NULL) {
- uio->uio_offset = TMPFS_DIRCOOKIE_EOF;
- node->tn_dir.tn_readdir_lastn = 0;
- node->tn_dir.tn_readdir_lastp = NULL;
- } else {
- node->tn_dir.tn_readdir_lastn = uio->uio_offset = tmpfs_dircookie(de);
- node->tn_dir.tn_readdir_lastp = de;
+ if (cnt == 0) {
+ if (de == NULL)
+ off = TMPFS_DIRCOOKIE_EOF;
+ else
+ off = tmpfs_dirent_cookie(de);
}
+ uio->uio_offset = off;
+ node->tn_dir.tn_readdir_lastn = off;
+ node->tn_dir.tn_readdir_lastp = de;
+
node->tn_status |= TMPFS_NODE_ACCESSED;
return error;
}
@@ -943,7 +1226,7 @@ tmpfs_dir_whiteout_remove(struct vnode *dvp, struct componentname *cnp)
de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp);
MPASS(de != NULL && de->td_node == NULL);
tmpfs_dir_detach(dvp, de);
- tmpfs_free_dirent(VFS_TO_TMPFS(dvp->v_mount), de, TRUE);
+ tmpfs_free_dirent(VFS_TO_TMPFS(dvp->v_mount), de);
}
/* --------------------------------------------------------------------- */
@@ -1436,3 +1719,15 @@ out:
return error;
}
+
+static __inline int
+tmpfs_dirtree_cmp(struct tmpfs_dirent *a, struct tmpfs_dirent *b)
+{
+ if (a->td_hash > b->td_hash)
+ return (1);
+ else if (a->td_hash < b->td_hash)
+ return (-1);
+ return (0);
+}
+
+RB_GENERATE_STATIC(tmpfs_dir, tmpfs_dirent, uh.td_entries, tmpfs_dirtree_cmp);
diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c
index b2aa786..8cf8693 100644
--- a/sys/fs/tmpfs/tmpfs_vfsops.c
+++ b/sys/fs/tmpfs/tmpfs_vfsops.c
@@ -294,19 +294,8 @@ tmpfs_unmount(struct mount *mp, int mntflags)
while (node != NULL) {
struct tmpfs_node *next;
- if (node->tn_type == VDIR) {
- struct tmpfs_dirent *de;
-
- de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
- while (de != NULL) {
- struct tmpfs_dirent *nde;
-
- nde = TAILQ_NEXT(de, td_entries);
- tmpfs_free_dirent(tmp, de, FALSE);
- de = nde;
- node->tn_size -= sizeof(struct tmpfs_dirent);
- }
- }
+ if (node->tn_type == VDIR)
+ tmpfs_dir_destroy(tmp, node);
next = LIST_NEXT(node, tn_entries);
tmpfs_free_node(tmp, node);
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 368e1ca..5e2ea65 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -847,7 +847,7 @@ tmpfs_remove(struct vop_remove_args *v)
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
* reclaimed. */
- tmpfs_free_dirent(tmp, de, TRUE);
+ tmpfs_free_dirent(tmp, de);
node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED;
error = 0;
@@ -1263,26 +1263,25 @@ tmpfs_rename(struct vop_rename_args *v)
fdnode->tn_links--;
TMPFS_NODE_UNLOCK(fdnode);
}
-
- /* Do the move: just remove the entry from the source directory
- * and insert it into the target one. */
- tmpfs_dir_detach(fdvp, de);
- if (fcnp->cn_flags & DOWHITEOUT)
- tmpfs_dir_whiteout_add(fdvp, fcnp);
- if (tcnp->cn_flags & ISWHITEOUT)
- tmpfs_dir_whiteout_remove(tdvp, tcnp);
- tmpfs_dir_attach(tdvp, de);
}
+ /* Do the move: just remove the entry from the source directory
+ * and insert it into the target one. */
+ tmpfs_dir_detach(fdvp, de);
+
+ if (fcnp->cn_flags & DOWHITEOUT)
+ tmpfs_dir_whiteout_add(fdvp, fcnp);
+ if (tcnp->cn_flags & ISWHITEOUT)
+ tmpfs_dir_whiteout_remove(tdvp, tcnp);
+
/* If the name has changed, we need to make it effective by changing
* it in the directory entry. */
if (newname != NULL) {
MPASS(tcnp->cn_namelen <= MAXNAMLEN);
- free(de->td_name, M_TMPFSNAME);
- de->td_namelen = (uint16_t)tcnp->cn_namelen;
- memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen);
- de->td_name = newname;
+ free(de->ud.td_name, M_TMPFSNAME);
+ de->ud.td_name = newname;
+ tmpfs_dirent_init(de, tcnp->cn_nameptr, tcnp->cn_namelen);
fnode->tn_status |= TMPFS_NODE_CHANGED;
tdnode->tn_status |= TMPFS_NODE_MODIFIED;
@@ -1291,15 +1290,20 @@ tmpfs_rename(struct vop_rename_args *v)
/* If we are overwriting an entry, we have to remove the old one
* from the target directory. */
if (tvp != NULL) {
+ struct tmpfs_dirent *tde;
+
/* Remove the old entry from the target directory. */
- de = tmpfs_dir_lookup(tdnode, tnode, tcnp);
- tmpfs_dir_detach(tdvp, de);
+ tde = tmpfs_dir_lookup(tdnode, tnode, tcnp);
+ tmpfs_dir_detach(tdvp, tde);
/* Free the directory entry we just deleted. Note that the
* node referred by it will not be removed until the vnode is
* really reclaimed. */
- tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de, TRUE);
+ tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), tde);
}
+
+ tmpfs_dir_attach(tdvp, de);
+
cache_purge(fvp);
if (tvp != NULL)
cache_purge(tvp);
@@ -1427,7 +1431,7 @@ tmpfs_rmdir(struct vop_rmdir_args *v)
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
* reclaimed. */
- tmpfs_free_dirent(tmp, de, TRUE);
+ tmpfs_free_dirent(tmp, de);
/* Release the deleted vnode (will destroy the node, notify
* interested parties and clean it from the cache). */
@@ -1473,8 +1477,8 @@ tmpfs_readdir(struct vop_readdir_args *v)
int *ncookies = v->a_ncookies;
int error;
- off_t startoff;
- off_t cnt = 0;
+ ssize_t startresid;
+ int cnt = 0;
struct tmpfs_node *node;
/* This operation only makes sense on directory nodes. */
@@ -1483,69 +1487,29 @@ tmpfs_readdir(struct vop_readdir_args *v)
node = VP_TO_TMPFS_DIR(vp);
- startoff = uio->uio_offset;
+ startresid = uio->uio_resid;
- if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) {
- error = tmpfs_dir_getdotdent(node, uio);
- if (error != 0)
- goto outok;
- cnt++;
- }
-
- if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
- error = tmpfs_dir_getdotdotdent(node, uio);
- if (error != 0)
- goto outok;
- cnt++;
+ if (cookies != NULL && ncookies != NULL) {
+ cnt = howmany(node->tn_size, sizeof(struct tmpfs_dirent)) + 2;
+ *cookies = malloc(cnt * sizeof(**cookies), M_TEMP, M_WAITOK);
+ *ncookies = 0;
}
- error = tmpfs_dir_getdents(node, uio, &cnt);
+ if (cnt == 0)
+ error = tmpfs_dir_getdents(node, uio, 0, NULL, NULL);
+ else
+ error = tmpfs_dir_getdents(node, uio, cnt, *cookies, ncookies);
-outok:
- MPASS(error >= -1);
+ if (error == EJUSTRETURN)
+ error = (uio->uio_resid != startresid) ? 0 : EINVAL;
- if (error == -1)
- error = (cnt != 0) ? 0 : EINVAL;
+ if (error != 0 && cnt != 0)
+ free(*cookies, M_TEMP);
if (eofflag != NULL)
*eofflag =
(error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
- /* Update NFS-related variables. */
- if (error == 0 && cookies != NULL && ncookies != NULL) {
- off_t i;
- off_t off = startoff;
- struct tmpfs_dirent *de = NULL;
-
- *ncookies = cnt;
- *cookies = malloc(cnt * sizeof(off_t), M_TEMP, M_WAITOK);
-
- for (i = 0; i < cnt; i++) {
- MPASS(off != TMPFS_DIRCOOKIE_EOF);
- if (off == TMPFS_DIRCOOKIE_DOT) {
- off = TMPFS_DIRCOOKIE_DOTDOT;
- } else {
- if (off == TMPFS_DIRCOOKIE_DOTDOT) {
- de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
- } else if (de != NULL) {
- de = TAILQ_NEXT(de, td_entries);
- } else {
- de = tmpfs_dir_lookupbycookie(node,
- off);
- MPASS(de != NULL);
- de = TAILQ_NEXT(de, td_entries);
- }
- if (de == NULL)
- off = TMPFS_DIRCOOKIE_EOF;
- else
- off = tmpfs_dircookie(de);
- }
-
- (*cookies)[i] = off;
- }
- MPASS(uio->uio_offset == off);
- }
-
return error;
}
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 76d09dd..3a808ba 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -37,6 +37,7 @@ 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
@@ -331,15 +332,6 @@ device usb # USB Bus (required)
device ukbd # Keyboard
device umass # Disks/Mass storage - Requires scbus and da
-# FireWire support
-device firewire # FireWire bus code
-# sbp(4) works for some systems but causes boot failure on others
-#device sbp # SCSI over FireWire (Requires scbus and da)
-device fwe # Ethernet over FireWire (non-standard!)
-device fwip # IP over FireWire (RFC 2734,3146)
-device dcons # Dumb console driver
-device dcons_crom # Configuration ROM for dcons
-
# Sound support
device sound # Generic sound driver (required)
device snd_cmi # CMedia CMI8338/CMI8738
diff --git a/sys/i386/xen/xen_machdep.c b/sys/i386/xen/xen_machdep.c
index f197976..3b3da6f 100644
--- a/sys/i386/xen/xen_machdep.c
+++ b/sys/i386/xen/xen_machdep.c
@@ -216,7 +216,9 @@ static mmu_update_t xpq_queue[MAX_VIRT_CPUS][XPQUEUE_SIZE];
#else
static mmu_update_t xpq_queue[XPQUEUE_SIZE];
+#ifdef INVARIANTS
static struct mmu_log xpq_queue_log[XPQUEUE_SIZE];
+#endif
static int xpq_idx = 0;
#define XPQ_QUEUE_LOG xpq_queue_log
diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC
index e22450b..196e5be 100644
--- a/sys/ia64/conf/GENERIC
+++ b/sys/ia64/conf/GENERIC
@@ -60,6 +60,7 @@ options SYSVSHM # SYSV-style shared memory
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Hash-based directory lookup scheme
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
+options QUOTA # Enable disk quotas for UFS
options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B RT extensions
# Debugging support. Always need this:
@@ -77,7 +78,6 @@ options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
# Various "busses"
-device firewire # FireWire bus code
device miibus # MII bus support (Ethernet)
device pci # PCI bus support
device scbus # SCSI bus (required for ATA/SCSI)
@@ -190,11 +190,6 @@ options IEEE80211_SUPPORT_MESH
# builds everything including AR5416 (and later 11n NIC) support.
options AH_SUPPORT_AR5416
-# FireWire support
-device fwip # IP over FireWire (RFC 2734,3146)
-# sbp(4) works for some systems but causes boot failure on others
-#device sbp # SCSI over FireWire (need scbus & da)
-
# Various (pseudo) devices
device ether # Ethernet support
device faith # IPv6-to-IPv4 relaying (translation)
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 3dd6521..50b47fb 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1074,7 +1074,9 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
q = td->td_proc;
if ((pid_t)id == WAIT_MYPGRP && (idtype == P_PID || idtype == P_PGID)) {
+ PROC_LOCK(q);
id = (id_t)q->p_pgid;
+ PROC_UNLOCK(q);
idtype = P_PGID;
}
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 98f0156..7962ae1 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -498,6 +498,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
case LK_DOWNGRADE:
_lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED,
file, line);
+ if (flags & LK_INTERLOCK)
+ class->lc_unlock(ilk);
return (0);
}
}
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index e2e4081..73dfd70 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -133,10 +133,10 @@ sleepinit(void)
* General sleep call. Suspends the current thread until a wakeup is
* performed on the specified identifier. The thread will then be made
* runnable with the specified priority. Sleeps at most timo/hz seconds
- * (0 means no timeout). If pri includes PCATCH flag, signals are checked
- * before and after sleeping, else signals are not checked. Returns 0 if
+ * (0 means no timeout). If pri includes the PCATCH flag, let signals
+ * interrupt the sleep, otherwise ignore them while sleeping. Returns 0 if
* awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
- * signal needs to be delivered, ERESTART is returned if the current system
+ * signal becomes pending, ERESTART is returned if the current system
* call should be restarted if possible, and EINTR is returned if the system
* call should be interrupted by the signal (return EINTR).
*
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index 510033f..fe10a87 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -160,7 +160,7 @@ static const char *const vm_bnames[] = {
"Plex86", /* Plex86 */
"Bochs", /* Bochs */
"Xen", /* Xen */
- "BHYVE", /* BHyVe */
+ "BHYVE", /* bhyve */
NULL
};
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 5926e15..3f10669 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -559,7 +559,7 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
if (error || fstype[fstypelen - 1] != '\0') {
error = EINVAL;
if (errmsg != NULL)
- strlcpy(errmsg, "Invalid fstype", errmsg_len);
+ strncpy(errmsg, "Invalid fstype", errmsg_len);
goto bail;
}
fspathlen = 0;
@@ -567,7 +567,7 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
if (error || fspath[fspathlen - 1] != '\0') {
error = EINVAL;
if (errmsg != NULL)
- strlcpy(errmsg, "Invalid fspath", errmsg_len);
+ strncpy(errmsg, "Invalid fspath", errmsg_len);
goto bail;
}
@@ -1447,7 +1447,7 @@ vfs_filteropt(struct vfsoptlist *opts, const char **legal)
if (ret != 0) {
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(opt->name, "errmsg") == 0) {
- strlcpy((char *)opt->value, errmsg, opt->len);
+ strncpy((char *)opt->value, errmsg, opt->len);
break;
}
}
@@ -1705,103 +1705,6 @@ vfs_copyopt(opts, name, dest, len)
return (ENOENT);
}
-/*
- * These are helper functions for filesystems to traverse all
- * their vnodes. See MNT_VNODE_FOREACH() in sys/mount.h.
- *
- * This interface has been deprecated in favor of MNT_VNODE_FOREACH_ALL.
- */
-
-MALLOC_DECLARE(M_VNODE_MARKER);
-
-struct vnode *
-__mnt_vnode_next(struct vnode **mvp, struct mount *mp)
-{
- struct vnode *vp;
-
- mtx_assert(MNT_MTX(mp), MA_OWNED);
-
- KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
- if (should_yield()) {
- MNT_IUNLOCK(mp);
- kern_yield(PRI_USER);
- MNT_ILOCK(mp);
- }
- vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
- while (vp != NULL && vp->v_type == VMARKER)
- vp = TAILQ_NEXT(vp, v_nmntvnodes);
-
- /* Check if we are done */
- if (vp == NULL) {
- __mnt_vnode_markerfree(mvp, mp);
- return (NULL);
- }
- TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
- TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
- return (vp);
-}
-
-struct vnode *
-__mnt_vnode_first(struct vnode **mvp, struct mount *mp)
-{
- struct vnode *vp;
-
- mtx_assert(MNT_MTX(mp), MA_OWNED);
-
- vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
- while (vp != NULL && vp->v_type == VMARKER)
- vp = TAILQ_NEXT(vp, v_nmntvnodes);
-
- /* Check if we are done */
- if (vp == NULL) {
- *mvp = NULL;
- return (NULL);
- }
- MNT_REF(mp);
- MNT_IUNLOCK(mp);
- *mvp = (struct vnode *) malloc(sizeof(struct vnode),
- M_VNODE_MARKER,
- M_WAITOK | M_ZERO);
- MNT_ILOCK(mp);
- (*mvp)->v_type = VMARKER;
-
- vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
- while (vp != NULL && vp->v_type == VMARKER)
- vp = TAILQ_NEXT(vp, v_nmntvnodes);
-
- /* Check if we are done */
- if (vp == NULL) {
- MNT_IUNLOCK(mp);
- free(*mvp, M_VNODE_MARKER);
- MNT_ILOCK(mp);
- *mvp = NULL;
- MNT_REL(mp);
- return (NULL);
- }
- (*mvp)->v_mount = mp;
- TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
- return (vp);
-}
-
-
-void
-__mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
-{
-
- if (*mvp == NULL)
- return;
-
- mtx_assert(MNT_MTX(mp), MA_OWNED);
-
- KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
- TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
- MNT_IUNLOCK(mp);
- free(*mvp, M_VNODE_MARKER);
- MNT_ILOCK(mp);
- *mvp = NULL;
- MNT_REL(mp);
-}
-
int
__vfs_statfs(struct mount *mp, struct statfs *sbp)
{
diff --git a/sys/mips/atheros/ar71xx_pci.c b/sys/mips/atheros/ar71xx_pci.c
index 126537c..9b88f60 100644
--- a/sys/mips/atheros/ar71xx_pci.c
+++ b/sys/mips/atheros/ar71xx_pci.c
@@ -81,6 +81,7 @@ struct ar71xx_pci_softc {
device_t sc_dev;
int sc_busno;
+ int sc_baseslot;
struct rman sc_mem_rman;
struct rman sc_irq_rman;
@@ -395,6 +396,16 @@ ar71xx_pci_attach(device_t dev)
AR71XX_PCI_IRQ_END) != 0)
panic("ar71xx_pci_attach: failed to set up IRQ rman");
+ /*
+ * Check if there is a base slot hint. Otherwise use default value.
+ */
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "baseslot", &sc->sc_baseslot) != 0) {
+ device_printf(dev,
+ "%s: missing hint '%s', default to AR71XX_PCI_BASE_SLOT\n",
+ __func__, "baseslot");
+ sc->sc_baseslot = AR71XX_PCI_BASE_SLOT;
+ }
ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0);
ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0);
@@ -648,11 +659,13 @@ ar71xx_pci_maxslots(device_t dev)
static int
ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin)
{
- if (pci_get_slot(device) < AR71XX_PCI_BASE_SLOT)
+ struct ar71xx_pci_softc *sc = device_get_softc(pcib);
+
+ if (pci_get_slot(device) < sc->sc_baseslot)
panic("%s: PCI slot %d is less then AR71XX_PCI_BASE_SLOT",
__func__, pci_get_slot(device));
- return (pci_get_slot(device) - AR71XX_PCI_BASE_SLOT);
+ return (pci_get_slot(device) - sc->sc_baseslot);
}
static device_method_t ar71xx_pci_methods[] = {
diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1
index 1d637d8..3ddb164 100644
--- a/sys/mips/conf/OCTEON1
+++ b/sys/mips/conf/OCTEON1
@@ -39,6 +39,7 @@ makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
# Board-specific support that cannot be auto-detected at runtime.
#options OCTEON_VENDOR_LANNER # Support for Lanner boards.
#options OCTEON_VENDOR_RADISYS # Support for Radisys boards.
+#options OCTEON_VENDOR_UBIQUITI # Support for Ubiquiti boards.
#options OCTEON_BOARD_CAPK_0100ND # Support for CAPK-0100nd.
# Compile for a specified Octeon model. If not specified, support for
diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h
index 5e71dd8..a84a0b8 100644
--- a/sys/net/if_pfsync.h
+++ b/sys/net/if_pfsync.h
@@ -1,6 +1,4 @@
-/* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $ */
-
-/*
+/*-
* Copyright (c) 2001 Michael Shalayeff
* All rights reserved.
*
@@ -26,7 +24,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
+/*-
* Copyright (c) 2008 David Gwynne <dlg@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -42,6 +40,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $
+ * $FreeBSD$
+ */
+
+
#ifndef _NET_IF_PFSYNC_H_
#define _NET_IF_PFSYNC_H_
@@ -63,20 +67,6 @@
#define PFSYNC_ACT_EOF 12 /* end of frame */
#define PFSYNC_ACT_MAX 13
-#define PFSYNC_ACTIONS "CLR ST", \
- "INS ST", \
- "INS ST ACK", \
- "UPD ST", \
- "UPD ST COMP", \
- "UPD ST REQ", \
- "DEL ST", \
- "DEL ST COMP", \
- "INS FR", \
- "DEL FR", \
- "BULK UPD STAT", \
- "TDB UPD", \
- "EOF"
-
#define PFSYNC_HMAC_LEN 20
/*
diff --git a/sys/net/zlib.c b/sys/net/zlib.c
index 8fc8cab..b348248 100644
--- a/sys/net/zlib.c
+++ b/sys/net/zlib.c
@@ -25,7 +25,14 @@
#define MY_ZCALLOC
#if defined(__FreeBSD__) && defined(_KERNEL)
-#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
+#define _tr_init _zlib104_tr_init
+#define _tr_align _zlib104_tr_align
+#define _tr_tally _zlib104_tr_tally
+#define _tr_flush_block _zlib104_tr_flush_block
+#define _tr_stored_block _zlib104_tr_stored_block
+#define inflate_fast _zlib104_inflate_fast
+#define inflate _zlib104_inflate
+#define zlibVersion _zlib104_Version
#endif
diff --git a/sys/net/zlib.h b/sys/net/zlib.h
index 44aa425..04941df 100644
--- a/sys/net/zlib.h
+++ b/sys/net/zlib.h
@@ -511,7 +511,7 @@ extern int EXPORT inflateInit OF((z_streamp strm));
*/
#if defined(__FreeBSD__) && defined(_KERNEL)
-#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
+#define inflate _zlib104_inflate /* FreeBSD already has an inflate :-( */
#endif
extern int EXPORT inflate OF((z_streamp strm, int flush));
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 675f3da..7087748 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -2324,5 +2324,19 @@ ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
ifp = vap->iv_ic->ic_ifp;
else
ifp = vap->iv_ifp;
- (void) ifp->if_transmit(ifp, m);
+
+ /*
+ * Free any node ref which this mbuf may have.
+ *
+ * Much like psq_mfree(), we assume that M_ENCAP nodes have
+ * node references.
+ */
+ if (ifp->if_transmit(ifp, m) != 0) {
+ /*
+ * XXX m is invalid (freed) at this point, determine M_ENCAP
+ * an alternate way.
+ */
+ if (ifp == vap->iv_ic->ic_ifp)
+ ieee80211_free_node(ni);
+ }
}
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index fcc4af1..2f8ec85 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -1227,6 +1227,8 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct mbuf *m, *next;
uint32_t metric = 0;
const uint8_t *addr;
+ int is_encap;
+ struct ieee80211_node *ni_encap;
if (ni == vap->iv_bss ||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
@@ -1403,11 +1405,21 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
(struct ieee80211_node *)(uintptr_t)
ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
for (; m != NULL; m = next) {
+ is_encap = !! (m->m_flags & M_ENCAP);
+ ni_encap = (struct ieee80211_node *) m->m_pkthdr.rcvif;
next = m->m_nextpkt;
m->m_nextpkt = NULL;
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
"flush queued frame %p len %d", m, m->m_pkthdr.len);
- ifp->if_transmit(ifp, m);
+
+ /*
+ * If the mbuf has M_ENCAP set, ensure we free it.
+ * Note that after if_transmit() is called, m is invalid.
+ */
+ if (ifp->if_transmit(ifp, m) != 0) {
+ if (is_encap)
+ ieee80211_free_node(ni_encap);
+ }
}
#undef IS_PROXY
#undef PROXIED_BY_US
diff --git a/sys/net80211/ieee80211_radiotap.h b/sys/net80211/ieee80211_radiotap.h
index f11ba73..388d70e 100644
--- a/sys/net80211/ieee80211_radiotap.h
+++ b/sys/net80211/ieee80211_radiotap.h
@@ -194,9 +194,20 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
- /* NB: gap for netbsd definitions */
+ /*
+ * 14-17 are from Linux, they overlap the netbsd-specific
+ * fields.
+ */
+ IEEE80211_RADIOTAP_RX_FLAGS = 14,
+ IEEE80211_RADIOTAP_TX_FLAGS = 15,
+ IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+ IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
IEEE80211_RADIOTAP_XCHANNEL = 18,
IEEE80211_RADIOTAP_MCS = 19,
+ IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
+
+ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOREXT = 30,
IEEE80211_RADIOTAP_EXT = 31,
};
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 6cb37e5..2b805c6 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -819,19 +819,14 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
return (error);
/*
- * Give the interface a chance to initialize if this is its first
- * address, and to validate the address if necessary.
- *
- * Historically, drivers managed IFF_UP flag theirselves, so we
- * need to check whether driver did that.
+ * Give the interface a chance to initialize
+ * if this is its first address,
+ * and to validate the address if necessary.
*/
- flags = ifp->if_flags;
if (ifp->if_ioctl != NULL &&
(error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)) != 0)
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
return (error);
- if ((ifp->if_flags & IFF_UP) && (flags & IFF_UP) == 0)
- if_up(ifp);
/*
* Be compatible with network classes, if netmask isn't supplied,
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 08dd259..e260e5d 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1874,18 +1874,9 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
ia->ia_addr = *sin6;
if (ifacount <= 1 && ifp->if_ioctl) {
- int flags;
-
- /*
- * Historically, drivers managed IFF_UP flag theirselves, so we
- * need to check whether driver did that.
- */
- flags = ifp->if_flags;
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
if (error)
return (error);
- if ((ifp->if_flags & IFF_UP) && (flags & IFF_UP) == 0)
- if_up(ifp);
}
ia->ia_ifa.ifa_metric = ifp->if_metric;
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index d2f6bc0..2b048a9 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -238,45 +238,11 @@ device bpf # Berkeley packet filter
#device ohci # OHCI PCI->USB interface
#device ehci # EHCI PCI->USB interface (USB 2.0)
#device usb # USB Bus (required)
-#device udbp # USB Double Bulk Pipe devices (needs netgraph)
-#device uhid # "Human Interface Devices"
#device ukbd # Keyboard
-#device ulpt # Printer
#device umass # Disks/Mass storage - Requires scbus and da
-#device ums # Mouse
-#device urio # Diamond Rio 500 MP3 player
-# USB Serial devices
-#device uark # Technologies ARK3116 based serial adapters
-#device ubsa # Belkin F5U103 and compatible serial adapters
-#device ubser # BWCT console serial adapters
-#device uftdi # For FTDI usb serial adapters
-#device uipaq # Some WinCE based devices
-#device uplcom # Prolific PL-2303 serial adapters
-#device uslcom # SI Labs CP2101/CP2102 serial adapters
-#device uvisor # Visor and Palm devices
-#device uvscom # USB serial support for DDI pocket's PHS
-# 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
-# USB Wireless
-#device rum # Ralink Technology RT2501USB wireless NICs
-#device uath # Atheros AR5523 wireless NICs
-#device ural # Ralink Technology RT2500USB wireless NICs
-#device zyd # ZyDAS zd1211/zd1211b wireless NICs
-
-# FireWire support
-#device firewire # FireWire bus code
-#device sbp # SCSI over FireWire (Requires scbus and da)
-#device fwe # Ethernet over FireWire (non-standard!)
# Sound support
#device sound # Generic sound driver (required)
#device snd_mss # Microsoft Sound System
#device "snd_sb16" # Sound Blaster 16
#device snd_sbc # Sound Blaster
-#device snd_uaudio # USB Audio
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
index 7f31d43..f7c3511 100644
--- a/sys/powerpc/conf/GENERIC
+++ b/sys/powerpc/conf/GENERIC
@@ -41,6 +41,7 @@ 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
@@ -183,12 +184,6 @@ device kue # Kawasaki LSI USB Ethernet
options IEEE80211_SUPPORT_MESH
options AH_SUPPORT_AR5416
-# FireWire support
-device firewire # FireWire bus code
-# sbp(4) works for some systems but causes boot failure on others
-device sbp # SCSI over FireWire (Requires scbus and da)
-device fwe # Ethernet over FireWire (non-standard!)
-
# Misc
device iicbus # I2C bus code
device kiic # Keywest I2C
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index 0e1555d..a2a283f 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -40,6 +40,7 @@ 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
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index bcd94cd..f9d3b93 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -36,6 +36,7 @@ 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
@@ -238,15 +239,6 @@ device usb # USB Bus (required)
device ukbd # Keyboard
device umass # Disks/Mass storage - Requires scbus and da
-# FireWire support
-device firewire # FireWire bus code
-# sbp(4) works for some systems but causes boot failure on others
-#device sbp # SCSI over FireWire (Requires scbus and da)
-device fwe # Ethernet over FireWire (non-standard!)
-device fwip # IP over FireWire (RFC 2734,3146)
-device dcons # Dumb console driver
-device dcons_crom # Configuration ROM for dcons
-
# Sound support
device sound # Generic sound driver (required)
device snd_audiocs # Crystal Semiconductor CS4231
diff --git a/sys/sparc64/sparc64/interrupt.S b/sys/sparc64/sparc64/interrupt.S
index fc144f4..179eeb6 100644
--- a/sys/sparc64/sparc64/interrupt.S
+++ b/sys/sparc64/sparc64/interrupt.S
@@ -83,13 +83,13 @@ ENTRY(intr_vector)
* The 2nd word points to code to execute and the 3rd is an argument
* to pass. Jump to it.
*/
- brnz,a,pt %g3, 1f
- srlx %g3, 60, %g6
+ brnz,pt %g3, 1f
/*
* NB: Zeus CPUs set some undocumented bits in the first data word.
*/
- jmpl %g4, %g0
and %g3, IV_MAX - 1, %g3
+ jmpl %g4, %g0
+ nop
/* NOTREACHED */
/*
@@ -98,7 +98,8 @@ ENTRY(intr_vector)
* 4 bits of the 1st data word specify a priority, and the 2nd and
* 3rd a function and argument.
*/
-1: brnz,a,pn %g6, 2f
+1: srlx %g3, 60, %g6
+ brnz,a,pn %g6, 2f
clr %g3
/*
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index ed2b002..992227c 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -225,29 +225,6 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *);
#define MNT_VNODE_FOREACH_ACTIVE_ABORT(mp, mvp) \
__mnt_vnode_markerfree_active(&(mvp), (mp))
-/*
- * Definitions for MNT_VNODE_FOREACH.
- *
- * This interface has been deprecated in favor of MNT_VNODE_FOREACH_ALL.
- */
-struct vnode *__mnt_vnode_next(struct vnode **mvp, struct mount *mp);
-struct vnode *__mnt_vnode_first(struct vnode **mvp, struct mount *mp);
-void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
-
-#define MNT_VNODE_FOREACH(vp, mp, mvp) \
- for (vp = __mnt_vnode_first(&(mvp), (mp)); \
- (vp) != NULL; vp = __mnt_vnode_next(&(mvp), (mp)))
-
-#define MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp) \
- __mnt_vnode_markerfree(&(mvp), (mp))
-
-#define MNT_VNODE_FOREACH_ABORT(mp, mvp) \
- do { \
- MNT_ILOCK(mp); \
- MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); \
- MNT_IUNLOCK(mp); \
- } while (0)
-
#define MNT_ILOCK(mp) mtx_lock(&(mp)->mnt_mtx)
#define MNT_ITRYLOCK(mp) mtx_trylock(&(mp)->mnt_mtx)
#define MNT_IUNLOCK(mp) mtx_unlock(&(mp)->mnt_mtx)
OpenPOWER on IntegriCloud