Merge 4.9.31 into android-4.9
Changes in 4.9.31
dccp/tcp: do not inherit mc_list from parent
driver: vrf: Fix one possible use-after-free issue
ipv6/dccp: do not inherit ipv6_mc_list from parent
s390/qeth: handle sysfs error during initialization
s390/qeth: unbreak OSM and OSN support
s390/qeth: avoid null pointer dereference on OSN
s390/qeth: add missing hash table initializations
bpf, arm64: fix faulty emission of map access in tail calls
netem: fix skb_orphan_partial()
net: fix compile error in skb_orphan_partial()
tcp: avoid fragmenting peculiar skbs in SACK
sctp: fix src address selection if using secondary addresses for ipv6
sctp: do not inherit ipv6_{mc|ac|fl}_list from parent
net/packet: fix missing net_device reference release
net/mlx5e: Use the correct pause values for ethtool advertising
net/mlx5e: Fix ethtool pause support and advertise reporting
tcp: eliminate negative reordering in tcp_clean_rtx_queue
net: Improve handling of failures on link and route dumps
ipv6: Prevent overrun when parsing v6 header options
ipv6: Check ip6_find_1stfragopt() return value properly.
bridge: netlink: check vlan_default_pvid range
qmi_wwan: add another Lenovo EM74xx device ID
bridge: start hello_timer when enabling KERNEL_STP in br_stp_start
ipv6: fix out of bound writes in __ip6_append_data()
bonding: fix accounting of active ports in 3ad
net/mlx5: Avoid using pending command interface slots
net: phy: marvell: Limit errata to 88m1101
vlan: Fix tcp checksum offloads in Q-in-Q vlans
be2net: Fix offload features for Q-in-Q packets
virtio-net: enable TSO/checksum offloads for Q-in-Q vlans
tcp: avoid fastopen API to be used on AF_UNSPEC
sctp: fix ICMP processing if skb is non-linear
ipv4: add reference counting to metrics
bpf: add bpf_clone_redirect to bpf_helper_changes_pkt_data
sparc: Fix -Wstringop-overflow warning
sparc/ftrace: Fix ftrace graph time measurement
fs/ufs: Set UFS default maximum bytes per file
powerpc/spufs: Fix hash faults for kernel regions
drivers/tty: 8250: only call fintek_8250_probe when doing port I/O
i2c: i2c-tiny-usb: fix buffer not being DMA capable
crypto: skcipher - Add missing API setkey checks
x86/MCE: Export memory_error()
acpi, nfit: Fix the memory error check in nfit_handle_mce()
Revert "ACPI / button: Change default behavior to lid_init_state=open"
mmc: sdhci-iproc: suppress spurious interrupt with Multiblock read
iscsi-target: Always wait for kthread_should_stop() before kthread exit
ibmvscsis: Clear left-over abort_cmd pointers
ibmvscsis: Fix the incorrect req_lim_delta
HID: wacom: Have wacom_tpc_irq guard against possible NULL dereference
nvme-rdma: support devices with queue size < 32
nvme: use blk_mq_start_hw_queues() in nvme_kill_queues()
nvme: avoid to use blk_mq_abort_requeue_list()
scsi: mpt3sas: Force request partial completion alignment
drm/radeon/ci: disable mclk switching for high refresh rates (v2)
drm/radeon: Unbreak HPD handling for r600+
drm/radeon: Fix vram_size/visible values in DRM_RADEON_GEM_INFO ioctl
pcmcia: remove left-over %Z format
ALSA: hda - apply STAC_9200_DELL_M22 quirk for Dell Latitude D430
mm/migrate: fix refcount handling when !hugepage_migration_supported()
mlock: fix mlock count can not decrease in race condition
mm: consider memblock reservations for deferred memory initialization sizing
RDMA/qib,hfi1: Fix MR reference count leak on write with immediate
x86/boot: Use CROSS_COMPILE prefix for readelf
ksm: prevent crash after write_protect_page fails
slub/memcg: cure the brainless abuse of sysfs attributes
mm/slub.c: trace free objects at KERN_INFO
drm/gma500/psb: Actually use VBT mode when it is found
xfs: Fix missed holes in SEEK_HOLE implementation
xfs: use ->b_state to fix buffer I/O accounting release race
xfs: fix off-by-one on max nr_pages in xfs_find_get_desired_pgoff()
xfs: verify inline directory data forks
xfs: rework the inline directory verifiers
xfs: fix kernel memory exposure problems
xfs: use dedicated log worker wq to avoid deadlock with cil wq
xfs: fix over-copying of getbmap parameters from userspace
xfs: actually report xattr extents via iomap
xfs: drop iolock from reclaim context to appease lockdep
xfs: fix integer truncation in xfs_bmap_remap_alloc
xfs: handle array index overrun in xfs_dir2_leaf_readbuf()
xfs: prevent multi-fsb dir readahead from reading random blocks
xfs: fix up quotacheck buffer list error handling
xfs: support ability to wait on new inodes
xfs: update ag iterator to support wait on new inodes
xfs: wait on new inodes during quotaoff dquot release
xfs: reserve enough blocks to handle btree splits when remapping
xfs: fix use-after-free in xfs_finish_page_writeback
xfs: fix indlen accounting error on partial delalloc conversion
xfs: BMAPX shouldn't barf on inline-format directories
xfs: bad assertion for delalloc an extent that start at i_size
xfs: xfs_trans_alloc_empty
xfs: avoid mount-time deadlock in CoW extent recovery
xfs: fix unaligned access in xfs_btree_visit_blocks
xfs: Fix off-by-in in loop termination in xfs_find_get_desired_pgoff()
Linux 4.9.31
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 9
|
PATCHLEVEL = 9
|
||||||
SUBLEVEL = 30
|
SUBLEVEL = 31
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = Roaring Lionus
|
NAME = Roaring Lionus
|
||||||
|
|
||||||
|
|||||||
@@ -252,8 +252,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
off = offsetof(struct bpf_array, ptrs);
|
off = offsetof(struct bpf_array, ptrs);
|
||||||
emit_a64_mov_i64(tmp, off, ctx);
|
emit_a64_mov_i64(tmp, off, ctx);
|
||||||
emit(A64_LDR64(tmp, r2, tmp), ctx);
|
emit(A64_ADD(1, tmp, r2, tmp), ctx);
|
||||||
emit(A64_LDR64(prg, tmp, r3), ctx);
|
emit(A64_LSL(1, prg, r3, 3), ctx);
|
||||||
|
emit(A64_LDR64(prg, tmp, prg), ctx);
|
||||||
emit(A64_CBZ(1, prg, jmp_offset), ctx);
|
emit(A64_CBZ(1, prg, jmp_offset), ctx);
|
||||||
|
|
||||||
/* goto *(prog->bpf_func + prologue_size); */
|
/* goto *(prog->bpf_func + prologue_size); */
|
||||||
|
|||||||
@@ -197,7 +197,9 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
|
|||||||
(REGION_ID(ea) != USER_REGION_ID)) {
|
(REGION_ID(ea) != USER_REGION_ID)) {
|
||||||
|
|
||||||
spin_unlock(&spu->register_lock);
|
spin_unlock(&spu->register_lock);
|
||||||
ret = hash_page(ea, _PAGE_PRESENT | _PAGE_READ, 0x300, dsisr);
|
ret = hash_page(ea,
|
||||||
|
_PAGE_PRESENT | _PAGE_READ | _PAGE_PRIVILEGED,
|
||||||
|
0x300, dsisr);
|
||||||
spin_lock(&spu->register_lock);
|
spin_lock(&spu->register_lock);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
|
|||||||
@@ -91,9 +91,9 @@ extern unsigned long pfn_base;
|
|||||||
* ZERO_PAGE is a global shared page that is always zero: used
|
* ZERO_PAGE is a global shared page that is always zero: used
|
||||||
* for zero-mapped memory areas etc..
|
* for zero-mapped memory areas etc..
|
||||||
*/
|
*/
|
||||||
extern unsigned long empty_zero_page;
|
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||||
|
|
||||||
#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
|
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In general all page table modifications should use the V8 atomic
|
* In general all page table modifications should use the V8 atomic
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ extern char reboot_command[];
|
|||||||
*/
|
*/
|
||||||
extern unsigned char boot_cpu_id;
|
extern unsigned char boot_cpu_id;
|
||||||
|
|
||||||
extern unsigned long empty_zero_page;
|
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
|
||||||
|
|
||||||
extern int serial_console;
|
extern int serial_console;
|
||||||
static inline int con_is_present(void)
|
static inline int con_is_present(void)
|
||||||
|
|||||||
@@ -130,18 +130,17 @@ unsigned long prepare_ftrace_return(unsigned long parent,
|
|||||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||||
return parent + 8UL;
|
return parent + 8UL;
|
||||||
|
|
||||||
|
trace.func = self_addr;
|
||||||
|
trace.depth = current->curr_ret_stack + 1;
|
||||||
|
|
||||||
|
/* Only trace if the calling function expects to */
|
||||||
|
if (!ftrace_graph_entry(&trace))
|
||||||
|
return parent + 8UL;
|
||||||
|
|
||||||
if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
|
if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
|
||||||
frame_pointer, NULL) == -EBUSY)
|
frame_pointer, NULL) == -EBUSY)
|
||||||
return parent + 8UL;
|
return parent + 8UL;
|
||||||
|
|
||||||
trace.func = self_addr;
|
|
||||||
|
|
||||||
/* Only trace if the calling function expects to */
|
|
||||||
if (!ftrace_graph_entry(&trace)) {
|
|
||||||
current->curr_ret_stack--;
|
|
||||||
return parent + 8UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return return_hooker;
|
return return_hooker;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ void __init mem_init(void)
|
|||||||
|
|
||||||
|
|
||||||
/* Saves us work later. */
|
/* Saves us work later. */
|
||||||
memset((void *)&empty_zero_page, 0, PAGE_SIZE);
|
memset((void *)empty_zero_page, 0, PAGE_SIZE);
|
||||||
|
|
||||||
i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
|
i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
|
|||||||
quiet_cmd_check_data_rel = DATAREL $@
|
quiet_cmd_check_data_rel = DATAREL $@
|
||||||
define cmd_check_data_rel
|
define cmd_check_data_rel
|
||||||
for obj in $(filter %.o,$^); do \
|
for obj in $(filter %.o,$^); do \
|
||||||
readelf -S $$obj | grep -qF .rel.local && { \
|
${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
|
||||||
echo "error: $$obj has data relocations!" >&2; \
|
echo "error: $$obj has data relocations!" >&2; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
} || true; \
|
} || true; \
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int mce_available(struct cpuinfo_x86 *c);
|
int mce_available(struct cpuinfo_x86 *c);
|
||||||
|
bool mce_is_memory_error(struct mce *m);
|
||||||
|
|
||||||
DECLARE_PER_CPU(unsigned, mce_exception_count);
|
DECLARE_PER_CPU(unsigned, mce_exception_count);
|
||||||
DECLARE_PER_CPU(unsigned, mce_poll_count);
|
DECLARE_PER_CPU(unsigned, mce_poll_count);
|
||||||
|
|||||||
@@ -598,16 +598,14 @@ static void mce_read_aux(struct mce *m, int i)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool memory_error(struct mce *m)
|
bool mce_is_memory_error(struct mce *m)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
if (m->cpuvendor == X86_VENDOR_AMD) {
|
||||||
|
|
||||||
if (c->x86_vendor == X86_VENDOR_AMD) {
|
|
||||||
/* ErrCodeExt[20:16] */
|
/* ErrCodeExt[20:16] */
|
||||||
u8 xec = (m->status >> 16) & 0x1f;
|
u8 xec = (m->status >> 16) & 0x1f;
|
||||||
|
|
||||||
return (xec == 0x0 || xec == 0x8);
|
return (xec == 0x0 || xec == 0x8);
|
||||||
} else if (c->x86_vendor == X86_VENDOR_INTEL) {
|
} else if (m->cpuvendor == X86_VENDOR_INTEL) {
|
||||||
/*
|
/*
|
||||||
* Intel SDM Volume 3B - 15.9.2 Compound Error Codes
|
* Intel SDM Volume 3B - 15.9.2 Compound Error Codes
|
||||||
*
|
*
|
||||||
@@ -628,6 +626,7 @@ static bool memory_error(struct mce *m)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mce_is_memory_error);
|
||||||
|
|
||||||
DEFINE_PER_CPU(unsigned, mce_poll_count);
|
DEFINE_PER_CPU(unsigned, mce_poll_count);
|
||||||
|
|
||||||
@@ -691,7 +690,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
|
|||||||
|
|
||||||
severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
|
severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
|
||||||
|
|
||||||
if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m))
|
if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m))
|
||||||
if (m.status & MCI_STATUS_ADDRV)
|
if (m.status & MCI_STATUS_ADDRV)
|
||||||
m.severity = severity;
|
m.severity = severity;
|
||||||
|
|
||||||
|
|||||||
+39
-1
@@ -221,6 +221,44 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm,
|
||||||
|
const u8 *key, unsigned int keylen)
|
||||||
|
{
|
||||||
|
unsigned long alignmask = crypto_skcipher_alignmask(tfm);
|
||||||
|
struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
|
||||||
|
u8 *buffer, *alignbuffer;
|
||||||
|
unsigned long absize;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
absize = keylen + alignmask;
|
||||||
|
buffer = kmalloc(absize, GFP_ATOMIC);
|
||||||
|
if (!buffer)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
|
||||||
|
memcpy(alignbuffer, key, keylen);
|
||||||
|
ret = cipher->setkey(tfm, alignbuffer, keylen);
|
||||||
|
kzfree(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
|
||||||
|
unsigned int keylen)
|
||||||
|
{
|
||||||
|
struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
|
||||||
|
unsigned long alignmask = crypto_skcipher_alignmask(tfm);
|
||||||
|
|
||||||
|
if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
|
||||||
|
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((unsigned long)key & alignmask)
|
||||||
|
return skcipher_setkey_unaligned(tfm, key, keylen);
|
||||||
|
|
||||||
|
return cipher->setkey(tfm, key, keylen);
|
||||||
|
}
|
||||||
|
|
||||||
static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
|
static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
|
||||||
{
|
{
|
||||||
struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
|
struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
|
||||||
@@ -241,7 +279,7 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
|
|||||||
tfm->__crt_alg->cra_type == &crypto_givcipher_type)
|
tfm->__crt_alg->cra_type == &crypto_givcipher_type)
|
||||||
return crypto_init_skcipher_ops_ablkcipher(tfm);
|
return crypto_init_skcipher_ops_ablkcipher(tfm);
|
||||||
|
|
||||||
skcipher->setkey = alg->setkey;
|
skcipher->setkey = skcipher_setkey;
|
||||||
skcipher->encrypt = alg->encrypt;
|
skcipher->encrypt = alg->encrypt;
|
||||||
skcipher->decrypt = alg->decrypt;
|
skcipher->decrypt = alg->decrypt;
|
||||||
skcipher->ivsize = alg->ivsize;
|
skcipher->ivsize = alg->ivsize;
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ struct acpi_button {
|
|||||||
|
|
||||||
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
|
static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
|
||||||
static struct acpi_device *lid_device;
|
static struct acpi_device *lid_device;
|
||||||
static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
|
static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
|
||||||
|
|
||||||
static unsigned long lid_report_interval __read_mostly = 500;
|
static unsigned long lid_report_interval __read_mostly = 500;
|
||||||
module_param(lid_report_interval, ulong, 0644);
|
module_param(lid_report_interval, ulong, 0644);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
|
|||||||
struct nfit_spa *nfit_spa;
|
struct nfit_spa *nfit_spa;
|
||||||
|
|
||||||
/* We only care about memory errors */
|
/* We only care about memory errors */
|
||||||
if (!(mce->status & MCACOD))
|
if (!mce_is_memory_error(mce))
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
|||||||
|
|
||||||
rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
|
rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
|
DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
|
||||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||||
if (rc == -ERESTARTSYS)
|
if (rc == -ERESTARTSYS)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
|||||||
for (i = 0; i < bytes_to_write; i++) {
|
for (i = 0; i < bytes_to_write; i++) {
|
||||||
rc = wait_for_bulk_out_ready(dev);
|
rc = wait_for_bulk_out_ready(dev);
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n",
|
DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n",
|
||||||
rc);
|
rc);
|
||||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||||
if (rc == -ERESTARTSYS)
|
if (rc == -ERESTARTSYS)
|
||||||
@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
|
|||||||
rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
|
rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
|
||||||
|
|
||||||
if (rc <= 0) {
|
if (rc <= 0) {
|
||||||
DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
|
DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
|
||||||
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
DEBUGP(2, dev, "<- cm4040_write (failed)\n");
|
||||||
if (rc == -ERESTARTSYS)
|
if (rc == -ERESTARTSYS)
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -774,20 +774,23 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
|||||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||||
mode_dev->panel_fixed_mode =
|
mode_dev->panel_fixed_mode =
|
||||||
drm_mode_duplicate(dev, scan);
|
drm_mode_duplicate(dev, scan);
|
||||||
|
DRM_DEBUG_KMS("Using mode from DDC\n");
|
||||||
goto out; /* FIXME: check for quirks */
|
goto out; /* FIXME: check for quirks */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Failed to get EDID, what about VBT? do we need this? */
|
/* Failed to get EDID, what about VBT? do we need this? */
|
||||||
if (mode_dev->vbt_mode)
|
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||||
mode_dev->panel_fixed_mode =
|
mode_dev->panel_fixed_mode =
|
||||||
drm_mode_duplicate(dev, mode_dev->vbt_mode);
|
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
|
||||||
|
|
||||||
if (!mode_dev->panel_fixed_mode)
|
if (mode_dev->panel_fixed_mode) {
|
||||||
if (dev_priv->lfp_lvds_vbt_mode)
|
mode_dev->panel_fixed_mode->type |=
|
||||||
mode_dev->panel_fixed_mode =
|
DRM_MODE_TYPE_PREFERRED;
|
||||||
drm_mode_duplicate(dev,
|
DRM_DEBUG_KMS("Using mode from VBT\n");
|
||||||
dev_priv->lfp_lvds_vbt_mode);
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we didn't get EDID, try checking if the panel is already turned
|
* If we didn't get EDID, try checking if the panel is already turned
|
||||||
@@ -804,6 +807,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
|||||||
if (mode_dev->panel_fixed_mode) {
|
if (mode_dev->panel_fixed_mode) {
|
||||||
mode_dev->panel_fixed_mode->type |=
|
mode_dev->panel_fixed_mode->type |=
|
||||||
DRM_MODE_TYPE_PREFERRED;
|
DRM_MODE_TYPE_PREFERRED;
|
||||||
|
DRM_DEBUG_KMS("Using pre-programmed mode\n");
|
||||||
goto out; /* FIXME: check for quirks */
|
goto out; /* FIXME: check for quirks */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev)
|
|||||||
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
|
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
|
||||||
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
|
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
|
||||||
|
|
||||||
|
/* disable mclk switching if the refresh is >120Hz, even if the
|
||||||
|
* blanking period would allow it
|
||||||
|
*/
|
||||||
|
if (r600_dpm_get_vrefresh(rdev) > 120)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (vblank_time < switch_limit)
|
if (vblank_time < switch_limit)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -7416,7 +7416,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_INT_ACK;
|
tmp |= DC_HPDx_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
@@ -7446,7 +7446,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_RX_INT_ACK;
|
tmp |= DC_HPDx_RX_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4933,7 +4933,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_INT_ACK;
|
tmp |= DC_HPDx_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
@@ -4964,7 +4964,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_RX_INT_ACK;
|
tmp |= DC_HPDx_RX_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3995,7 +3995,7 @@ static void r600_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
|
if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_INT_ACK;
|
tmp |= DC_HPDx_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,9 +97,10 @@
|
|||||||
* 2.46.0 - Add PFP_SYNC_ME support on evergreen
|
* 2.46.0 - Add PFP_SYNC_ME support on evergreen
|
||||||
* 2.47.0 - Add UVD_NO_OP register support
|
* 2.47.0 - Add UVD_NO_OP register support
|
||||||
* 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
|
* 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
|
||||||
|
* 2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
|
||||||
*/
|
*/
|
||||||
#define KMS_DRIVER_MAJOR 2
|
#define KMS_DRIVER_MAJOR 2
|
||||||
#define KMS_DRIVER_MINOR 48
|
#define KMS_DRIVER_MINOR 49
|
||||||
#define KMS_DRIVER_PATCHLEVEL 0
|
#define KMS_DRIVER_PATCHLEVEL 0
|
||||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||||
|
|||||||
@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
man = &rdev->mman.bdev.man[TTM_PL_VRAM];
|
man = &rdev->mman.bdev.man[TTM_PL_VRAM];
|
||||||
|
|
||||||
args->vram_size = rdev->mc.real_vram_size;
|
args->vram_size = (u64)man->size << PAGE_SHIFT;
|
||||||
args->vram_visible = (u64)man->size << PAGE_SHIFT;
|
args->vram_visible = rdev->mc.visible_vram_size;
|
||||||
args->vram_visible -= rdev->vram_pin_size;
|
args->vram_visible -= rdev->vram_pin_size;
|
||||||
args->gart_size = rdev->mc.gtt_size;
|
args->gart_size = rdev->mc.gtt_size;
|
||||||
args->gart_size -= rdev->gart_pin_size;
|
args->gart_size -= rdev->gart_pin_size;
|
||||||
|
|||||||
@@ -6330,7 +6330,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_INT_ACK;
|
tmp |= DC_HPDx_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
@@ -6361,7 +6361,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
|
|||||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
tmp = RREG32(DC_HPD6_INT_CONTROL);
|
||||||
tmp |= DC_HPDx_RX_INT_ACK;
|
tmp |= DC_HPDx_RX_INT_ACK;
|
||||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-23
@@ -1400,37 +1400,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
|
|||||||
{
|
{
|
||||||
unsigned char *data = wacom->data;
|
unsigned char *data = wacom->data;
|
||||||
|
|
||||||
if (wacom->pen_input)
|
if (wacom->pen_input) {
|
||||||
dev_dbg(wacom->pen_input->dev.parent,
|
dev_dbg(wacom->pen_input->dev.parent,
|
||||||
"%s: received report #%d\n", __func__, data[0]);
|
"%s: received report #%d\n", __func__, data[0]);
|
||||||
else if (wacom->touch_input)
|
|
||||||
|
if (len == WACOM_PKGLEN_PENABLED ||
|
||||||
|
data[0] == WACOM_REPORT_PENABLED)
|
||||||
|
return wacom_tpc_pen(wacom);
|
||||||
|
}
|
||||||
|
else if (wacom->touch_input) {
|
||||||
dev_dbg(wacom->touch_input->dev.parent,
|
dev_dbg(wacom->touch_input->dev.parent,
|
||||||
"%s: received report #%d\n", __func__, data[0]);
|
"%s: received report #%d\n", __func__, data[0]);
|
||||||
|
|
||||||
switch (len) {
|
switch (len) {
|
||||||
case WACOM_PKGLEN_TPC1FG:
|
case WACOM_PKGLEN_TPC1FG:
|
||||||
return wacom_tpc_single_touch(wacom, len);
|
|
||||||
|
|
||||||
case WACOM_PKGLEN_TPC2FG:
|
|
||||||
return wacom_tpc_mt_touch(wacom);
|
|
||||||
|
|
||||||
case WACOM_PKGLEN_PENABLED:
|
|
||||||
return wacom_tpc_pen(wacom);
|
|
||||||
|
|
||||||
default:
|
|
||||||
switch (data[0]) {
|
|
||||||
case WACOM_REPORT_TPC1FG:
|
|
||||||
case WACOM_REPORT_TPCHID:
|
|
||||||
case WACOM_REPORT_TPCST:
|
|
||||||
case WACOM_REPORT_TPC1FGE:
|
|
||||||
return wacom_tpc_single_touch(wacom, len);
|
return wacom_tpc_single_touch(wacom, len);
|
||||||
|
|
||||||
case WACOM_REPORT_TPCMT:
|
case WACOM_PKGLEN_TPC2FG:
|
||||||
case WACOM_REPORT_TPCMT2:
|
return wacom_tpc_mt_touch(wacom);
|
||||||
return wacom_mt_touch(wacom);
|
|
||||||
|
|
||||||
case WACOM_REPORT_PENABLED:
|
default:
|
||||||
return wacom_tpc_pen(wacom);
|
switch (data[0]) {
|
||||||
|
case WACOM_REPORT_TPC1FG:
|
||||||
|
case WACOM_REPORT_TPCHID:
|
||||||
|
case WACOM_REPORT_TPCST:
|
||||||
|
case WACOM_REPORT_TPC1FGE:
|
||||||
|
return wacom_tpc_single_touch(wacom, len);
|
||||||
|
|
||||||
|
case WACOM_REPORT_TPCMT:
|
||||||
|
case WACOM_REPORT_TPCMT2:
|
||||||
|
return wacom_mt_touch(wacom);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd,
|
|||||||
int value, int index, void *data, int len)
|
int value, int index, void *data, int len)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
|
void *dmadata = kmalloc(len, GFP_KERNEL);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!dmadata)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* do control transfer */
|
/* do control transfer */
|
||||||
return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
||||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
|
||||||
USB_DIR_IN, value, index, data, len, 2000);
|
USB_DIR_IN, value, index, dmadata, len, 2000);
|
||||||
|
|
||||||
|
memcpy(data, dmadata, len);
|
||||||
|
kfree(dmadata);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
int value, int index, void *data, int len)
|
int value, int index, void *data, int len)
|
||||||
{
|
{
|
||||||
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
|
void *dmadata = kmemdup(data, len, GFP_KERNEL);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!dmadata)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* do control transfer */
|
/* do control transfer */
|
||||||
return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
||||||
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
value, index, data, len, 2000);
|
value, index, dmadata, len, 2000);
|
||||||
|
|
||||||
|
kfree(dmadata);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
||||||
|
|||||||
@@ -2366,8 +2366,11 @@ send_last:
|
|||||||
ret = hfi1_rvt_get_rwqe(qp, 1);
|
ret = hfi1_rvt_get_rwqe(qp, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto nack_op_err;
|
goto nack_op_err;
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
/* peer will send again */
|
||||||
|
rvt_put_ss(&qp->r_sge);
|
||||||
goto rnr_nak;
|
goto rnr_nak;
|
||||||
|
}
|
||||||
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
||||||
wc.wc_flags = IB_WC_WITH_IMM;
|
wc.wc_flags = IB_WC_WITH_IMM;
|
||||||
goto send_last;
|
goto send_last;
|
||||||
|
|||||||
@@ -2067,8 +2067,10 @@ send_last:
|
|||||||
ret = qib_get_rwqe(qp, 1);
|
ret = qib_get_rwqe(qp, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto nack_op_err;
|
goto nack_op_err;
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
rvt_put_ss(&qp->r_sge);
|
||||||
goto rnr_nak;
|
goto rnr_nak;
|
||||||
|
}
|
||||||
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
wc.ex.imm_data = ohdr->u.rc.imm_data;
|
||||||
hdrsize += 4;
|
hdrsize += 4;
|
||||||
wc.wc_flags = IB_WC_WITH_IMM;
|
wc.wc_flags = IB_WC_WITH_IMM;
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ static const struct sdhci_ops sdhci_iproc_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
|
static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
|
||||||
.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
|
.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
|
||||||
|
SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
|
||||||
.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
|
.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
|
||||||
.ops = &sdhci_iproc_ops,
|
.ops = &sdhci_iproc_ops,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2573,7 +2573,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ad_info->aggregator_id = aggregator->aggregator_identifier;
|
ad_info->aggregator_id = aggregator->aggregator_identifier;
|
||||||
ad_info->ports = aggregator->num_of_ports;
|
ad_info->ports = __agg_active_ports(aggregator);
|
||||||
ad_info->actor_key = aggregator->actor_oper_aggregator_key;
|
ad_info->actor_key = aggregator->actor_oper_aggregator_key;
|
||||||
ad_info->partner_key = aggregator->partner_oper_aggregator_key;
|
ad_info->partner_key = aggregator->partner_oper_aggregator_key;
|
||||||
ether_addr_copy(ad_info->partner_system,
|
ether_addr_copy(ad_info->partner_system,
|
||||||
|
|||||||
@@ -5144,9 +5144,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
|
|||||||
struct be_adapter *adapter = netdev_priv(dev);
|
struct be_adapter *adapter = netdev_priv(dev);
|
||||||
u8 l4_hdr = 0;
|
u8 l4_hdr = 0;
|
||||||
|
|
||||||
/* The code below restricts offload features for some tunneled packets.
|
/* The code below restricts offload features for some tunneled and
|
||||||
|
* Q-in-Q packets.
|
||||||
* Offload features for normal (non tunnel) packets are unchanged.
|
* Offload features for normal (non tunnel) packets are unchanged.
|
||||||
*/
|
*/
|
||||||
|
features = vlan_features_check(skb, features);
|
||||||
if (!skb->encapsulation ||
|
if (!skb->encapsulation ||
|
||||||
!(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
|
!(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
|
||||||
return features;
|
return features;
|
||||||
|
|||||||
@@ -767,7 +767,7 @@ static void cb_timeout_handler(struct work_struct *work)
|
|||||||
mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
|
mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
|
||||||
mlx5_command_str(msg_to_opcode(ent->in)),
|
mlx5_command_str(msg_to_opcode(ent->in)),
|
||||||
msg_to_opcode(ent->in));
|
msg_to_opcode(ent->in));
|
||||||
mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
|
mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmd_work_handler(struct work_struct *work)
|
static void cmd_work_handler(struct work_struct *work)
|
||||||
@@ -797,6 +797,7 @@ static void cmd_work_handler(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd->ent_arr[ent->idx] = ent;
|
cmd->ent_arr[ent->idx] = ent;
|
||||||
|
set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
|
||||||
lay = get_inst(cmd, ent->idx);
|
lay = get_inst(cmd, ent->idx);
|
||||||
ent->lay = lay;
|
ent->lay = lay;
|
||||||
memset(lay, 0, sizeof(*lay));
|
memset(lay, 0, sizeof(*lay));
|
||||||
@@ -818,6 +819,20 @@ static void cmd_work_handler(struct work_struct *work)
|
|||||||
if (ent->callback)
|
if (ent->callback)
|
||||||
schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
|
schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
|
||||||
|
|
||||||
|
/* Skip sending command to fw if internal error */
|
||||||
|
if (pci_channel_offline(dev->pdev) ||
|
||||||
|
dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
|
||||||
|
u8 status = 0;
|
||||||
|
u32 drv_synd;
|
||||||
|
|
||||||
|
ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status);
|
||||||
|
MLX5_SET(mbox_out, ent->out, status, status);
|
||||||
|
MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
|
||||||
|
|
||||||
|
mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* ring doorbell after the descriptor is valid */
|
/* ring doorbell after the descriptor is valid */
|
||||||
mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
|
mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
|
||||||
wmb();
|
wmb();
|
||||||
@@ -828,7 +843,7 @@ static void cmd_work_handler(struct work_struct *work)
|
|||||||
poll_timeout(ent);
|
poll_timeout(ent);
|
||||||
/* make sure we read the descriptor after ownership is SW */
|
/* make sure we read the descriptor after ownership is SW */
|
||||||
rmb();
|
rmb();
|
||||||
mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
|
mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,7 +887,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
|
|||||||
wait_for_completion(&ent->done);
|
wait_for_completion(&ent->done);
|
||||||
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
|
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
|
||||||
ent->ret = -ETIMEDOUT;
|
ent->ret = -ETIMEDOUT;
|
||||||
mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
|
mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ent->ret;
|
err = ent->ret;
|
||||||
@@ -1369,7 +1384,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
|
void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced)
|
||||||
{
|
{
|
||||||
struct mlx5_cmd *cmd = &dev->cmd;
|
struct mlx5_cmd *cmd = &dev->cmd;
|
||||||
struct mlx5_cmd_work_ent *ent;
|
struct mlx5_cmd_work_ent *ent;
|
||||||
@@ -1389,6 +1404,19 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
|
|||||||
struct semaphore *sem;
|
struct semaphore *sem;
|
||||||
|
|
||||||
ent = cmd->ent_arr[i];
|
ent = cmd->ent_arr[i];
|
||||||
|
|
||||||
|
/* if we already completed the command, ignore it */
|
||||||
|
if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP,
|
||||||
|
&ent->state)) {
|
||||||
|
/* only real completion can free the cmd slot */
|
||||||
|
if (!forced) {
|
||||||
|
mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
|
||||||
|
ent->idx);
|
||||||
|
free_ent(cmd, ent->idx);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ent->callback)
|
if (ent->callback)
|
||||||
cancel_delayed_work(&ent->cb_timeout_work);
|
cancel_delayed_work(&ent->cb_timeout_work);
|
||||||
if (ent->page_queue)
|
if (ent->page_queue)
|
||||||
@@ -1411,7 +1439,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
|
|||||||
mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
|
mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
|
||||||
ent->ret, deliv_status_to_str(ent->status), ent->status);
|
ent->ret, deliv_status_to_str(ent->status), ent->status);
|
||||||
}
|
}
|
||||||
free_ent(cmd, ent->idx);
|
|
||||||
|
/* only real completion will free the entry slot */
|
||||||
|
if (!forced)
|
||||||
|
free_ent(cmd, ent->idx);
|
||||||
|
|
||||||
if (ent->callback) {
|
if (ent->callback) {
|
||||||
ds = ent->ts2 - ent->ts1;
|
ds = ent->ts2 - ent->ts1;
|
||||||
|
|||||||
@@ -751,7 +751,6 @@ static void get_supported(u32 eth_proto_cap,
|
|||||||
ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
|
ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
|
||||||
ptys2ethtool_supported_link(supported, eth_proto_cap);
|
ptys2ethtool_supported_link(supported, eth_proto_cap);
|
||||||
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
|
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
|
||||||
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
|
static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
|
||||||
@@ -761,7 +760,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
|
|||||||
unsigned long *advertising = link_ksettings->link_modes.advertising;
|
unsigned long *advertising = link_ksettings->link_modes.advertising;
|
||||||
|
|
||||||
ptys2ethtool_adver_link(advertising, eth_proto_cap);
|
ptys2ethtool_adver_link(advertising, eth_proto_cap);
|
||||||
if (tx_pause)
|
if (rx_pause)
|
||||||
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
|
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
|
||||||
if (tx_pause ^ rx_pause)
|
if (tx_pause ^ rx_pause)
|
||||||
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
|
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
|
||||||
@@ -806,6 +805,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
|
|||||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||||
struct mlx5_core_dev *mdev = priv->mdev;
|
struct mlx5_core_dev *mdev = priv->mdev;
|
||||||
u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
|
u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
|
||||||
|
u32 rx_pause = 0;
|
||||||
|
u32 tx_pause = 0;
|
||||||
u32 eth_proto_cap;
|
u32 eth_proto_cap;
|
||||||
u32 eth_proto_admin;
|
u32 eth_proto_admin;
|
||||||
u32 eth_proto_lp;
|
u32 eth_proto_lp;
|
||||||
@@ -828,11 +829,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
|
|||||||
an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
|
an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
|
||||||
an_status = MLX5_GET(ptys_reg, out, an_status);
|
an_status = MLX5_GET(ptys_reg, out, an_status);
|
||||||
|
|
||||||
|
mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
|
||||||
|
|
||||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
|
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
|
||||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
|
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
|
||||||
|
|
||||||
get_supported(eth_proto_cap, link_ksettings);
|
get_supported(eth_proto_cap, link_ksettings);
|
||||||
get_advertising(eth_proto_admin, 0, 0, link_ksettings);
|
get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);
|
||||||
get_speed_duplex(netdev, eth_proto_oper, link_ksettings);
|
get_speed_duplex(netdev, eth_proto_oper, link_ksettings);
|
||||||
|
|
||||||
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
|
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MLX5_EVENT_TYPE_CMD:
|
case MLX5_EVENT_TYPE_CMD:
|
||||||
mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector));
|
mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MLX5_EVENT_TYPE_PORT_CHANGE:
|
case MLX5_EVENT_TYPE_PORT_CHANGE:
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static void trigger_cmd_completions(struct mlx5_core_dev *dev)
|
|||||||
spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
|
spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
|
||||||
|
|
||||||
mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
|
mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
|
||||||
mlx5_cmd_comp_handler(dev, vector);
|
mlx5_cmd_comp_handler(dev, vector, true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
no_trig:
|
no_trig:
|
||||||
|
|||||||
+37
-29
@@ -240,34 +240,6 @@ static int marvell_config_aneg(struct phy_device *phydev)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* The Marvell PHY has an errata which requires
|
|
||||||
* that certain registers get written in order
|
|
||||||
* to restart autonegotiation */
|
|
||||||
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
|
|
||||||
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = phy_write(phydev, 0x1d, 0x1f);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = phy_write(phydev, 0x1e, 0x200c);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = phy_write(phydev, 0x1d, 0x5);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = phy_write(phydev, 0x1e, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = phy_write(phydev, 0x1e, 0x100);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = marvell_set_polarity(phydev, phydev->mdix);
|
err = marvell_set_polarity(phydev, phydev->mdix);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
@@ -301,6 +273,42 @@ static int marvell_config_aneg(struct phy_device *phydev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int m88e1101_config_aneg(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* This Marvell PHY has an errata which requires
|
||||||
|
* that certain registers get written in order
|
||||||
|
* to restart autonegotiation
|
||||||
|
*/
|
||||||
|
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = phy_write(phydev, 0x1d, 0x1f);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = phy_write(phydev, 0x1e, 0x200c);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = phy_write(phydev, 0x1d, 0x5);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = phy_write(phydev, 0x1e, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = phy_write(phydev, 0x1e, 0x100);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return marvell_config_aneg(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
static int m88e1111_config_aneg(struct phy_device *phydev)
|
static int m88e1111_config_aneg(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@@ -1491,7 +1499,7 @@ static struct phy_driver marvell_drivers[] = {
|
|||||||
.probe = marvell_probe,
|
.probe = marvell_probe,
|
||||||
.flags = PHY_HAS_INTERRUPT,
|
.flags = PHY_HAS_INTERRUPT,
|
||||||
.config_init = &marvell_config_init,
|
.config_init = &marvell_config_init,
|
||||||
.config_aneg = &marvell_config_aneg,
|
.config_aneg = &m88e1101_config_aneg,
|
||||||
.read_status = &genphy_read_status,
|
.read_status = &genphy_read_status,
|
||||||
.ack_interrupt = &marvell_ack_interrupt,
|
.ack_interrupt = &marvell_ack_interrupt,
|
||||||
.config_intr = &marvell_config_intr,
|
.config_intr = &marvell_config_intr,
|
||||||
|
|||||||
@@ -897,6 +897,8 @@ static const struct usb_device_id products[] = {
|
|||||||
{QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */
|
{QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx */
|
||||||
{QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */
|
{QMI_FIXED_INTF(0x1199, 0x9079, 8)}, /* Sierra Wireless EM74xx */
|
||||||
{QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */
|
{QMI_FIXED_INTF(0x1199, 0x9079, 10)}, /* Sierra Wireless EM74xx */
|
||||||
|
{QMI_FIXED_INTF(0x1199, 0x907b, 8)}, /* Sierra Wireless EM74xx */
|
||||||
|
{QMI_FIXED_INTF(0x1199, 0x907b, 10)}, /* Sierra Wireless EM74xx */
|
||||||
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
|
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
|
||||||
{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
|
{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
|
||||||
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
|
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */
|
||||||
|
|||||||
@@ -1456,6 +1456,7 @@ static const struct net_device_ops virtnet_netdev = {
|
|||||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||||
.ndo_busy_poll = virtnet_busy_poll,
|
.ndo_busy_poll = virtnet_busy_poll,
|
||||||
#endif
|
#endif
|
||||||
|
.ndo_features_check = passthru_features_check,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void virtnet_config_changed_work(struct work_struct *work)
|
static void virtnet_config_changed_work(struct work_struct *work)
|
||||||
|
|||||||
+2
-1
@@ -850,6 +850,7 @@ static u32 vrf_fib_table(const struct net_device *dev)
|
|||||||
|
|
||||||
static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
kfree_skb(skb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,7 +860,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,
|
|||||||
{
|
{
|
||||||
struct net *net = dev_net(dev);
|
struct net *net = dev_net(dev);
|
||||||
|
|
||||||
if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
|
if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1)
|
||||||
skb = NULL; /* kfree_skb(skb) handled by nf code */
|
skb = NULL; /* kfree_skb(skb) handled by nf code */
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
|
|||||||
@@ -1725,7 +1725,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
|
|||||||
sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
|
sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
|
||||||
&nvme_ns_attr_group);
|
&nvme_ns_attr_group);
|
||||||
del_gendisk(ns->disk);
|
del_gendisk(ns->disk);
|
||||||
blk_mq_abort_requeue_list(ns->queue);
|
|
||||||
blk_cleanup_queue(ns->queue);
|
blk_cleanup_queue(ns->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2048,8 +2047,16 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
|
|||||||
continue;
|
continue;
|
||||||
revalidate_disk(ns->disk);
|
revalidate_disk(ns->disk);
|
||||||
blk_set_queue_dying(ns->queue);
|
blk_set_queue_dying(ns->queue);
|
||||||
blk_mq_abort_requeue_list(ns->queue);
|
|
||||||
blk_mq_start_stopped_hw_queues(ns->queue, true);
|
/*
|
||||||
|
* Forcibly start all queues to avoid having stuck requests.
|
||||||
|
* Note that we must ensure the queues are not stopped
|
||||||
|
* when the final removal happens.
|
||||||
|
*/
|
||||||
|
blk_mq_start_hw_queues(ns->queue);
|
||||||
|
|
||||||
|
/* draining requests in requeue list */
|
||||||
|
blk_mq_kick_requeue_list(ns->queue);
|
||||||
}
|
}
|
||||||
mutex_unlock(&ctrl->namespaces_mutex);
|
mutex_unlock(&ctrl->namespaces_mutex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1011,6 +1011,19 @@ static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
|
|||||||
nvme_rdma_wr_error(cq, wc, "SEND");
|
nvme_rdma_wr_error(cq, wc, "SEND");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue)
|
||||||
|
{
|
||||||
|
int sig_limit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We signal completion every queue depth/2 and also handle the
|
||||||
|
* degenerated case of a device with queue_depth=1, where we
|
||||||
|
* would need to signal every message.
|
||||||
|
*/
|
||||||
|
sig_limit = max(queue->queue_size / 2, 1);
|
||||||
|
return (++queue->sig_count % sig_limit) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
|
static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
|
||||||
struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge,
|
struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge,
|
||||||
struct ib_send_wr *first, bool flush)
|
struct ib_send_wr *first, bool flush)
|
||||||
@@ -1038,9 +1051,6 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
|
|||||||
* Would have been way to obvious to handle this in hardware or
|
* Would have been way to obvious to handle this in hardware or
|
||||||
* at least the RDMA stack..
|
* at least the RDMA stack..
|
||||||
*
|
*
|
||||||
* This messy and racy code sniplet is copy and pasted from the iSER
|
|
||||||
* initiator, and the magic '32' comes from there as well.
|
|
||||||
*
|
|
||||||
* Always signal the flushes. The magic request used for the flush
|
* Always signal the flushes. The magic request used for the flush
|
||||||
* sequencer is not allocated in our driver's tagset and it's
|
* sequencer is not allocated in our driver's tagset and it's
|
||||||
* triggered to be freed by blk_cleanup_queue(). So we need to
|
* triggered to be freed by blk_cleanup_queue(). So we need to
|
||||||
@@ -1048,7 +1058,7 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
|
|||||||
* embeded in request's payload, is not freed when __ib_process_cq()
|
* embeded in request's payload, is not freed when __ib_process_cq()
|
||||||
* calls wr_cqe->done().
|
* calls wr_cqe->done().
|
||||||
*/
|
*/
|
||||||
if ((++queue->sig_count % 32) == 0 || flush)
|
if (nvme_rdma_queue_sig_limit(queue) || flush)
|
||||||
wr.send_flags |= IB_SEND_SIGNALED;
|
wr.send_flags |= IB_SEND_SIGNALED;
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
|
|||||||
@@ -718,6 +718,7 @@ enum qeth_discipline_id {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct qeth_discipline {
|
struct qeth_discipline {
|
||||||
|
const struct device_type *devtype;
|
||||||
void (*start_poll)(struct ccw_device *, int, unsigned long);
|
void (*start_poll)(struct ccw_device *, int, unsigned long);
|
||||||
qdio_handler_t *input_handler;
|
qdio_handler_t *input_handler;
|
||||||
qdio_handler_t *output_handler;
|
qdio_handler_t *output_handler;
|
||||||
@@ -893,6 +894,9 @@ extern struct qeth_discipline qeth_l2_discipline;
|
|||||||
extern struct qeth_discipline qeth_l3_discipline;
|
extern struct qeth_discipline qeth_l3_discipline;
|
||||||
extern const struct attribute_group *qeth_generic_attr_groups[];
|
extern const struct attribute_group *qeth_generic_attr_groups[];
|
||||||
extern const struct attribute_group *qeth_osn_attr_groups[];
|
extern const struct attribute_group *qeth_osn_attr_groups[];
|
||||||
|
extern const struct attribute_group qeth_device_attr_group;
|
||||||
|
extern const struct attribute_group qeth_device_blkt_group;
|
||||||
|
extern const struct device_type qeth_generic_devtype;
|
||||||
extern struct workqueue_struct *qeth_wq;
|
extern struct workqueue_struct *qeth_wq;
|
||||||
|
|
||||||
int qeth_card_hw_is_reachable(struct qeth_card *);
|
int qeth_card_hw_is_reachable(struct qeth_card *);
|
||||||
|
|||||||
@@ -5462,10 +5462,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
|
|||||||
card->discipline = NULL;
|
card->discipline = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct device_type qeth_generic_devtype = {
|
const struct device_type qeth_generic_devtype = {
|
||||||
.name = "qeth_generic",
|
.name = "qeth_generic",
|
||||||
.groups = qeth_generic_attr_groups,
|
.groups = qeth_generic_attr_groups,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(qeth_generic_devtype);
|
||||||
|
|
||||||
static const struct device_type qeth_osn_devtype = {
|
static const struct device_type qeth_osn_devtype = {
|
||||||
.name = "qeth_osn",
|
.name = "qeth_osn",
|
||||||
.groups = qeth_osn_attr_groups,
|
.groups = qeth_osn_attr_groups,
|
||||||
@@ -5591,23 +5593,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||||||
goto err_card;
|
goto err_card;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card->info.type == QETH_CARD_TYPE_OSN)
|
|
||||||
gdev->dev.type = &qeth_osn_devtype;
|
|
||||||
else
|
|
||||||
gdev->dev.type = &qeth_generic_devtype;
|
|
||||||
|
|
||||||
switch (card->info.type) {
|
switch (card->info.type) {
|
||||||
case QETH_CARD_TYPE_OSN:
|
case QETH_CARD_TYPE_OSN:
|
||||||
case QETH_CARD_TYPE_OSM:
|
case QETH_CARD_TYPE_OSM:
|
||||||
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
|
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_card;
|
goto err_card;
|
||||||
|
|
||||||
|
gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
|
||||||
|
? card->discipline->devtype
|
||||||
|
: &qeth_osn_devtype;
|
||||||
rc = card->discipline->setup(card->gdev);
|
rc = card->discipline->setup(card->gdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_disc;
|
goto err_disc;
|
||||||
case QETH_CARD_TYPE_OSD:
|
break;
|
||||||
case QETH_CARD_TYPE_OSX:
|
|
||||||
default:
|
default:
|
||||||
|
gdev->dev.type = &qeth_generic_devtype;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5663,8 +5664,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto err;
|
goto err;
|
||||||
rc = card->discipline->setup(card->gdev);
|
rc = card->discipline->setup(card->gdev);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
qeth_core_free_discipline(card);
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rc = card->discipline->set_online(gdev);
|
rc = card->discipline->set_online(gdev);
|
||||||
err:
|
err:
|
||||||
|
|||||||
@@ -413,12 +413,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||||||
|
|
||||||
if (card->options.layer2 == newdis)
|
if (card->options.layer2 == newdis)
|
||||||
goto out;
|
goto out;
|
||||||
else {
|
if (card->info.type == QETH_CARD_TYPE_OSM) {
|
||||||
card->info.mac_bits = 0;
|
/* fixed layer, can't switch */
|
||||||
if (card->discipline) {
|
rc = -EOPNOTSUPP;
|
||||||
card->discipline->remove(card->gdev);
|
goto out;
|
||||||
qeth_core_free_discipline(card);
|
}
|
||||||
}
|
|
||||||
|
card->info.mac_bits = 0;
|
||||||
|
if (card->discipline) {
|
||||||
|
card->discipline->remove(card->gdev);
|
||||||
|
qeth_core_free_discipline(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = qeth_core_load_discipline(card, newdis);
|
rc = qeth_core_load_discipline(card, newdis);
|
||||||
@@ -426,6 +430,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = card->discipline->setup(card->gdev);
|
rc = card->discipline->setup(card->gdev);
|
||||||
|
if (rc)
|
||||||
|
qeth_core_free_discipline(card);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&card->discipline_mutex);
|
mutex_unlock(&card->discipline_mutex);
|
||||||
return rc ? rc : count;
|
return rc ? rc : count;
|
||||||
@@ -703,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
|
|||||||
&dev_attr_inter_jumbo.attr,
|
&dev_attr_inter_jumbo.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static struct attribute_group qeth_device_blkt_group = {
|
const struct attribute_group qeth_device_blkt_group = {
|
||||||
.name = "blkt",
|
.name = "blkt",
|
||||||
.attrs = qeth_blkt_device_attrs,
|
.attrs = qeth_blkt_device_attrs,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
|
||||||
|
|
||||||
static struct attribute *qeth_device_attrs[] = {
|
static struct attribute *qeth_device_attrs[] = {
|
||||||
&dev_attr_state.attr,
|
&dev_attr_state.attr,
|
||||||
@@ -726,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = {
|
|||||||
&dev_attr_switch_attrs.attr,
|
&dev_attr_switch_attrs.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static struct attribute_group qeth_device_attr_group = {
|
const struct attribute_group qeth_device_attr_group = {
|
||||||
.attrs = qeth_device_attrs,
|
.attrs = qeth_device_attrs,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(qeth_device_attr_group);
|
||||||
|
|
||||||
const struct attribute_group *qeth_generic_attr_groups[] = {
|
const struct attribute_group *qeth_generic_attr_groups[] = {
|
||||||
&qeth_device_attr_group,
|
&qeth_device_attr_group,
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "qeth_core.h"
|
#include "qeth_core.h"
|
||||||
|
|
||||||
|
extern const struct attribute_group *qeth_l2_attr_groups[];
|
||||||
|
|
||||||
int qeth_l2_create_device_attributes(struct device *);
|
int qeth_l2_create_device_attributes(struct device *);
|
||||||
void qeth_l2_remove_device_attributes(struct device *);
|
void qeth_l2_remove_device_attributes(struct device *);
|
||||||
void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
|
void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
|
||||||
|
|||||||
@@ -1021,11 +1021,21 @@ static int qeth_l2_stop(struct net_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct device_type qeth_l2_devtype = {
|
||||||
|
.name = "qeth_layer2",
|
||||||
|
.groups = qeth_l2_attr_groups,
|
||||||
|
};
|
||||||
|
|
||||||
static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
|
static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
|
||||||
{
|
{
|
||||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||||
|
int rc;
|
||||||
|
|
||||||
qeth_l2_create_device_attributes(&gdev->dev);
|
if (gdev->dev.type == &qeth_generic_devtype) {
|
||||||
|
rc = qeth_l2_create_device_attributes(&gdev->dev);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
INIT_LIST_HEAD(&card->vid_list);
|
INIT_LIST_HEAD(&card->vid_list);
|
||||||
hash_init(card->mac_htable);
|
hash_init(card->mac_htable);
|
||||||
card->options.layer2 = 1;
|
card->options.layer2 = 1;
|
||||||
@@ -1037,7 +1047,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
|
|||||||
{
|
{
|
||||||
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
|
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
|
||||||
|
|
||||||
qeth_l2_remove_device_attributes(&cgdev->dev);
|
if (cgdev->dev.type == &qeth_generic_devtype)
|
||||||
|
qeth_l2_remove_device_attributes(&cgdev->dev);
|
||||||
qeth_set_allowed_threads(card, 0, 1);
|
qeth_set_allowed_threads(card, 0, 1);
|
||||||
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
|
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
|
||||||
|
|
||||||
@@ -1095,7 +1106,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
|
|||||||
case QETH_CARD_TYPE_OSN:
|
case QETH_CARD_TYPE_OSN:
|
||||||
card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
|
card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
|
||||||
ether_setup);
|
ether_setup);
|
||||||
card->dev->flags |= IFF_NOARP;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
card->dev = alloc_etherdev(0);
|
card->dev = alloc_etherdev(0);
|
||||||
@@ -1108,9 +1118,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
|
|||||||
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
|
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
|
||||||
card->dev->mtu = card->info.initial_mtu;
|
card->dev->mtu = card->info.initial_mtu;
|
||||||
card->dev->netdev_ops = &qeth_l2_netdev_ops;
|
card->dev->netdev_ops = &qeth_l2_netdev_ops;
|
||||||
card->dev->ethtool_ops =
|
if (card->info.type == QETH_CARD_TYPE_OSN) {
|
||||||
(card->info.type != QETH_CARD_TYPE_OSN) ?
|
card->dev->ethtool_ops = &qeth_l2_osn_ops;
|
||||||
&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
|
card->dev->flags |= IFF_NOARP;
|
||||||
|
} else {
|
||||||
|
card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
|
||||||
|
}
|
||||||
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
|
card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
|
||||||
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
|
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
|
||||||
card->dev->hw_features = NETIF_F_SG;
|
card->dev->hw_features = NETIF_F_SG;
|
||||||
@@ -1434,6 +1447,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct qeth_discipline qeth_l2_discipline = {
|
struct qeth_discipline qeth_l2_discipline = {
|
||||||
|
.devtype = &qeth_l2_devtype,
|
||||||
.start_poll = qeth_qdio_start_poll,
|
.start_poll = qeth_qdio_start_poll,
|
||||||
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
|
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
|
||||||
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
|
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
|
||||||
|
|||||||
@@ -272,3 +272,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
|
|||||||
} else
|
} else
|
||||||
qeth_bridgeport_an_set(card, 0);
|
qeth_bridgeport_an_set(card, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct attribute_group *qeth_l2_attr_groups[] = {
|
||||||
|
&qeth_device_attr_group,
|
||||||
|
&qeth_device_blkt_group,
|
||||||
|
/* l2 specific, see l2_{create,remove}_device_attributes(): */
|
||||||
|
&qeth_l2_bridgeport_attr_group,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|||||||
@@ -3157,8 +3157,13 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||||||
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
|
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
|
||||||
{
|
{
|
||||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||||
|
int rc;
|
||||||
|
|
||||||
qeth_l3_create_device_attributes(&gdev->dev);
|
rc = qeth_l3_create_device_attributes(&gdev->dev);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
hash_init(card->ip_htable);
|
||||||
|
hash_init(card->ip_mc_htable);
|
||||||
card->options.layer2 = 0;
|
card->options.layer2 = 0;
|
||||||
card->info.hwtrap = 0;
|
card->info.hwtrap = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3450,6 +3455,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct qeth_discipline qeth_l3_discipline = {
|
struct qeth_discipline qeth_l3_discipline = {
|
||||||
|
.devtype = &qeth_generic_devtype,
|
||||||
.start_poll = qeth_qdio_start_poll,
|
.start_poll = qeth_qdio_start_poll,
|
||||||
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
|
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
|
||||||
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
|
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
|
||||||
|
|||||||
@@ -1169,6 +1169,8 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
|
|||||||
cmd = list_first_entry_or_null(&vscsi->free_cmd,
|
cmd = list_first_entry_or_null(&vscsi->free_cmd,
|
||||||
struct ibmvscsis_cmd, list);
|
struct ibmvscsis_cmd, list);
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
|
if (cmd->abort_cmd)
|
||||||
|
cmd->abort_cmd = NULL;
|
||||||
cmd->flags &= ~(DELAY_SEND);
|
cmd->flags &= ~(DELAY_SEND);
|
||||||
list_del(&cmd->list);
|
list_del(&cmd->list);
|
||||||
cmd->iue = iue;
|
cmd->iue = iue;
|
||||||
@@ -1773,6 +1775,7 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
|
|||||||
if (cmd->abort_cmd) {
|
if (cmd->abort_cmd) {
|
||||||
retry = true;
|
retry = true;
|
||||||
cmd->abort_cmd->flags &= ~(DELAY_SEND);
|
cmd->abort_cmd->flags &= ~(DELAY_SEND);
|
||||||
|
cmd->abort_cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1787,6 +1790,25 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
|
|||||||
list_del(&cmd->list);
|
list_del(&cmd->list);
|
||||||
ibmvscsis_free_cmd_resources(vscsi,
|
ibmvscsis_free_cmd_resources(vscsi,
|
||||||
cmd);
|
cmd);
|
||||||
|
/*
|
||||||
|
* With a successfully aborted op
|
||||||
|
* through LIO we want to increment the
|
||||||
|
* the vscsi credit so that when we dont
|
||||||
|
* send a rsp to the original scsi abort
|
||||||
|
* op (h_send_crq), but the tm rsp to
|
||||||
|
* the abort is sent, the credit is
|
||||||
|
* correctly sent with the abort tm rsp.
|
||||||
|
* We would need 1 for the abort tm rsp
|
||||||
|
* and 1 credit for the aborted scsi op.
|
||||||
|
* Thus we need to increment here.
|
||||||
|
* Also we want to increment the credit
|
||||||
|
* here because we want to make sure
|
||||||
|
* cmd is actually released first
|
||||||
|
* otherwise the client will think it
|
||||||
|
* it can send a new cmd, and we could
|
||||||
|
* find ourselves short of cmd elements.
|
||||||
|
*/
|
||||||
|
vscsi->credit += 1;
|
||||||
} else {
|
} else {
|
||||||
iue = cmd->iue;
|
iue = cmd->iue;
|
||||||
|
|
||||||
@@ -2961,10 +2983,7 @@ static long srp_build_response(struct scsi_info *vscsi,
|
|||||||
|
|
||||||
rsp->opcode = SRP_RSP;
|
rsp->opcode = SRP_RSP;
|
||||||
|
|
||||||
if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING)
|
rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
|
||||||
rsp->req_lim_delta = cpu_to_be32(vscsi->credit);
|
|
||||||
else
|
|
||||||
rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
|
|
||||||
rsp->tag = cmd->rsp.tag;
|
rsp->tag = cmd->rsp.tag;
|
||||||
rsp->flags = 0;
|
rsp->flags = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -4634,6 +4634,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
|
|||||||
struct MPT3SAS_DEVICE *sas_device_priv_data;
|
struct MPT3SAS_DEVICE *sas_device_priv_data;
|
||||||
u32 response_code = 0;
|
u32 response_code = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
unsigned int sector_sz;
|
||||||
|
|
||||||
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
|
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
|
||||||
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
|
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
|
||||||
@@ -4692,6 +4693,20 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
|
xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
|
||||||
|
|
||||||
|
/* In case of bogus fw or device, we could end up having
|
||||||
|
* unaligned partial completion. We can force alignment here,
|
||||||
|
* then scsi-ml does not need to handle this misbehavior.
|
||||||
|
*/
|
||||||
|
sector_sz = scmd->device->sector_size;
|
||||||
|
if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
|
||||||
|
xfer_cnt % sector_sz)) {
|
||||||
|
sdev_printk(KERN_INFO, scmd->device,
|
||||||
|
"unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
|
||||||
|
xfer_cnt, sector_sz);
|
||||||
|
xfer_cnt = round_down(xfer_cnt, sector_sz);
|
||||||
|
}
|
||||||
|
|
||||||
scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
|
scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
|
||||||
if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
|
if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
|
||||||
log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
|
log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
|
||||||
|
|||||||
@@ -3798,6 +3798,8 @@ int iscsi_target_tx_thread(void *arg)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct iscsi_conn *conn = arg;
|
struct iscsi_conn *conn = arg;
|
||||||
|
bool conn_freed = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow ourselves to be interrupted by SIGINT so that a
|
* Allow ourselves to be interrupted by SIGINT so that a
|
||||||
* connection recovery / failure event can be triggered externally.
|
* connection recovery / failure event can be triggered externally.
|
||||||
@@ -3823,12 +3825,14 @@ get_immediate:
|
|||||||
goto transport_err;
|
goto transport_err;
|
||||||
|
|
||||||
ret = iscsit_handle_response_queue(conn);
|
ret = iscsit_handle_response_queue(conn);
|
||||||
if (ret == 1)
|
if (ret == 1) {
|
||||||
goto get_immediate;
|
goto get_immediate;
|
||||||
else if (ret == -ECONNRESET)
|
} else if (ret == -ECONNRESET) {
|
||||||
|
conn_freed = true;
|
||||||
goto out;
|
goto out;
|
||||||
else if (ret < 0)
|
} else if (ret < 0) {
|
||||||
goto transport_err;
|
goto transport_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transport_err:
|
transport_err:
|
||||||
@@ -3838,8 +3842,13 @@ transport_err:
|
|||||||
* responsible for cleaning up the early connection failure.
|
* responsible for cleaning up the early connection failure.
|
||||||
*/
|
*/
|
||||||
if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
|
if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
|
||||||
iscsit_take_action_for_connection_exit(conn);
|
iscsit_take_action_for_connection_exit(conn, &conn_freed);
|
||||||
out:
|
out:
|
||||||
|
if (!conn_freed) {
|
||||||
|
while (!kthread_should_stop()) {
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4012,6 +4021,7 @@ int iscsi_target_rx_thread(void *arg)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct iscsi_conn *conn = arg;
|
struct iscsi_conn *conn = arg;
|
||||||
|
bool conn_freed = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow ourselves to be interrupted by SIGINT so that a
|
* Allow ourselves to be interrupted by SIGINT so that a
|
||||||
@@ -4024,7 +4034,7 @@ int iscsi_target_rx_thread(void *arg)
|
|||||||
*/
|
*/
|
||||||
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
|
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
|
||||||
if (rc < 0 || iscsi_target_check_conn_state(conn))
|
if (rc < 0 || iscsi_target_check_conn_state(conn))
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
if (!conn->conn_transport->iscsit_get_rx_pdu)
|
if (!conn->conn_transport->iscsit_get_rx_pdu)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4033,7 +4043,15 @@ int iscsi_target_rx_thread(void *arg)
|
|||||||
|
|
||||||
if (!signal_pending(current))
|
if (!signal_pending(current))
|
||||||
atomic_set(&conn->transport_failed, 1);
|
atomic_set(&conn->transport_failed, 1);
|
||||||
iscsit_take_action_for_connection_exit(conn);
|
iscsit_take_action_for_connection_exit(conn, &conn_freed);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (!conn_freed) {
|
||||||
|
while (!kthread_should_stop()) {
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -930,8 +930,10 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed)
|
||||||
{
|
{
|
||||||
|
*conn_freed = false;
|
||||||
|
|
||||||
spin_lock_bh(&conn->state_lock);
|
spin_lock_bh(&conn->state_lock);
|
||||||
if (atomic_read(&conn->connection_exit)) {
|
if (atomic_read(&conn->connection_exit)) {
|
||||||
spin_unlock_bh(&conn->state_lock);
|
spin_unlock_bh(&conn->state_lock);
|
||||||
@@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
|||||||
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
|
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
|
||||||
spin_unlock_bh(&conn->state_lock);
|
spin_unlock_bh(&conn->state_lock);
|
||||||
iscsit_close_connection(conn);
|
iscsit_close_connection(conn);
|
||||||
|
*conn_freed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
|||||||
spin_unlock_bh(&conn->state_lock);
|
spin_unlock_bh(&conn->state_lock);
|
||||||
|
|
||||||
iscsit_handle_connection_cleanup(conn);
|
iscsit_handle_connection_cleanup(conn);
|
||||||
|
*conn_freed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,6 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *);
|
|||||||
extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
|
extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
|
||||||
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
|
extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
|
||||||
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
|
extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
|
||||||
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
|
extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *);
|
||||||
|
|
||||||
#endif /*** ISCSI_TARGET_ERL0_H ***/
|
#endif /*** ISCSI_TARGET_ERL0_H ***/
|
||||||
|
|||||||
@@ -1460,5 +1460,9 @@ int iscsi_target_login_thread(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!kthread_should_stop()) {
|
||||||
|
msleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1320,7 +1320,7 @@ out_lock:
|
|||||||
/*
|
/*
|
||||||
* Check if the device is a Fintek F81216A
|
* Check if the device is a Fintek F81216A
|
||||||
*/
|
*/
|
||||||
if (port->type == PORT_16550A)
|
if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
|
||||||
fintek_8250_probe(up);
|
fintek_8250_probe(up);
|
||||||
|
|
||||||
if (up->capabilities != old_capabilities) {
|
if (up->capabilities != old_capabilities) {
|
||||||
|
|||||||
+2
-3
@@ -812,9 +812,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
uspi->s_dirblksize = UFS_SECTOR_SIZE;
|
uspi->s_dirblksize = UFS_SECTOR_SIZE;
|
||||||
super_block_offset=UFS_SBLOCK;
|
super_block_offset=UFS_SBLOCK;
|
||||||
|
|
||||||
/* Keep 2Gig file limit. Some UFS variants need to override
|
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||||
this but as I don't know which I'll let those in the know loosen
|
|
||||||
the rules */
|
|
||||||
switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
|
switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
|
||||||
case UFS_MOUNT_UFSTYPE_44BSD:
|
case UFS_MOUNT_UFSTYPE_44BSD:
|
||||||
UFSD("ufstype=44bsd\n");
|
UFSD("ufstype=44bsd\n");
|
||||||
|
|||||||
@@ -2208,8 +2208,10 @@ xfs_bmap_add_extent_delay_real(
|
|||||||
}
|
}
|
||||||
temp = xfs_bmap_worst_indlen(bma->ip, temp);
|
temp = xfs_bmap_worst_indlen(bma->ip, temp);
|
||||||
temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
|
temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
|
||||||
diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
|
diff = (int)(temp + temp2 -
|
||||||
(bma->cur ? bma->cur->bc_private.b.allocated : 0));
|
(startblockval(PREV.br_startblock) -
|
||||||
|
(bma->cur ?
|
||||||
|
bma->cur->bc_private.b.allocated : 0)));
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
error = xfs_mod_fdblocks(bma->ip->i_mount,
|
error = xfs_mod_fdblocks(bma->ip->i_mount,
|
||||||
-((int64_t)diff), false);
|
-((int64_t)diff), false);
|
||||||
@@ -2266,7 +2268,6 @@ xfs_bmap_add_extent_delay_real(
|
|||||||
temp = da_new;
|
temp = da_new;
|
||||||
if (bma->cur)
|
if (bma->cur)
|
||||||
temp += bma->cur->bc_private.b.allocated;
|
temp += bma->cur->bc_private.b.allocated;
|
||||||
ASSERT(temp <= da_old);
|
|
||||||
if (temp < da_old)
|
if (temp < da_old)
|
||||||
xfs_mod_fdblocks(bma->ip->i_mount,
|
xfs_mod_fdblocks(bma->ip->i_mount,
|
||||||
(int64_t)(da_old - temp), false);
|
(int64_t)(da_old - temp), false);
|
||||||
@@ -3964,7 +3965,7 @@ xfs_bmap_remap_alloc(
|
|||||||
{
|
{
|
||||||
struct xfs_trans *tp = ap->tp;
|
struct xfs_trans *tp = ap->tp;
|
||||||
struct xfs_mount *mp = tp->t_mountp;
|
struct xfs_mount *mp = tp->t_mountp;
|
||||||
xfs_agblock_t bno;
|
xfs_fsblock_t bno;
|
||||||
struct xfs_alloc_arg args;
|
struct xfs_alloc_arg args;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
|||||||
@@ -4376,7 +4376,7 @@ xfs_btree_visit_blocks(
|
|||||||
xfs_btree_readahead_ptr(cur, ptr, 1);
|
xfs_btree_readahead_ptr(cur, ptr, 1);
|
||||||
|
|
||||||
/* save for the next iteration of the loop */
|
/* save for the next iteration of the loop */
|
||||||
lptr = *ptr;
|
xfs_btree_copy_ptrs(cur, &lptr, ptr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for each buffer in the level */
|
/* for each buffer in the level */
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
|
|||||||
extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
|
extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
|
||||||
extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
|
extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
|
||||||
extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
|
extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
|
||||||
|
extern int xfs_dir2_sf_verify(struct xfs_inode *ip);
|
||||||
|
|
||||||
/* xfs_dir2_readdir.c */
|
/* xfs_dir2_readdir.c */
|
||||||
extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx,
|
extern int xfs_readdir(struct xfs_inode *dp, struct dir_context *ctx,
|
||||||
|
|||||||
@@ -629,6 +629,112 @@ xfs_dir2_sf_check(
|
|||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
/* Verify the consistency of an inline directory. */
|
||||||
|
int
|
||||||
|
xfs_dir2_sf_verify(
|
||||||
|
struct xfs_inode *ip)
|
||||||
|
{
|
||||||
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
|
struct xfs_dir2_sf_hdr *sfp;
|
||||||
|
struct xfs_dir2_sf_entry *sfep;
|
||||||
|
struct xfs_dir2_sf_entry *next_sfep;
|
||||||
|
char *endp;
|
||||||
|
const struct xfs_dir_ops *dops;
|
||||||
|
struct xfs_ifork *ifp;
|
||||||
|
xfs_ino_t ino;
|
||||||
|
int i;
|
||||||
|
int i8count;
|
||||||
|
int offset;
|
||||||
|
int size;
|
||||||
|
int error;
|
||||||
|
__uint8_t filetype;
|
||||||
|
|
||||||
|
ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
|
||||||
|
/*
|
||||||
|
* xfs_iread calls us before xfs_setup_inode sets up ip->d_ops,
|
||||||
|
* so we can only trust the mountpoint to have the right pointer.
|
||||||
|
*/
|
||||||
|
dops = xfs_dir_get_ops(mp, NULL);
|
||||||
|
|
||||||
|
ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
|
||||||
|
sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
|
||||||
|
size = ifp->if_bytes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give up if the directory is way too short.
|
||||||
|
*/
|
||||||
|
if (size <= offsetof(struct xfs_dir2_sf_hdr, parent) ||
|
||||||
|
size < xfs_dir2_sf_hdr_size(sfp->i8count))
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
endp = (char *)sfp + size;
|
||||||
|
|
||||||
|
/* Check .. entry */
|
||||||
|
ino = dops->sf_get_parent_ino(sfp);
|
||||||
|
i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
|
||||||
|
error = xfs_dir_ino_validate(mp, ino);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
offset = dops->data_first_offset;
|
||||||
|
|
||||||
|
/* Check all reported entries */
|
||||||
|
sfep = xfs_dir2_sf_firstentry(sfp);
|
||||||
|
for (i = 0; i < sfp->count; i++) {
|
||||||
|
/*
|
||||||
|
* struct xfs_dir2_sf_entry has a variable length.
|
||||||
|
* Check the fixed-offset parts of the structure are
|
||||||
|
* within the data buffer.
|
||||||
|
*/
|
||||||
|
if (((char *)sfep + sizeof(*sfep)) >= endp)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
/* Don't allow names with known bad length. */
|
||||||
|
if (sfep->namelen == 0)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the variable-length part of the structure is
|
||||||
|
* within the data buffer. The next entry starts after the
|
||||||
|
* name component, so nextentry is an acceptable test.
|
||||||
|
*/
|
||||||
|
next_sfep = dops->sf_nextentry(sfp, sfep);
|
||||||
|
if (endp < (char *)next_sfep)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
/* Check that the offsets always increase. */
|
||||||
|
if (xfs_dir2_sf_get_offset(sfep) < offset)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
/* Check the inode number. */
|
||||||
|
ino = dops->sf_get_ino(sfp, sfep);
|
||||||
|
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
|
||||||
|
error = xfs_dir_ino_validate(mp, ino);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
/* Check the file type. */
|
||||||
|
filetype = dops->sf_get_ftype(sfep);
|
||||||
|
if (filetype >= XFS_DIR3_FT_MAX)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
offset = xfs_dir2_sf_get_offset(sfep) +
|
||||||
|
dops->data_entsize(sfep->namelen);
|
||||||
|
|
||||||
|
sfep = next_sfep;
|
||||||
|
}
|
||||||
|
if (i8count != sfp->i8count)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
if ((void *)sfep != (void *)endp)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
/* Make sure this whole thing ought to be in local format. */
|
||||||
|
if (offset + (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
|
||||||
|
(uint)sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize)
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new (shortform) directory.
|
* Create a new (shortform) directory.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#include "xfs_trace.h"
|
#include "xfs_trace.h"
|
||||||
#include "xfs_attr_sf.h"
|
#include "xfs_attr_sf.h"
|
||||||
#include "xfs_da_format.h"
|
#include "xfs_da_format.h"
|
||||||
|
#include "xfs_da_btree.h"
|
||||||
|
#include "xfs_dir2_priv.h"
|
||||||
|
|
||||||
kmem_zone_t *xfs_ifork_zone;
|
kmem_zone_t *xfs_ifork_zone;
|
||||||
|
|
||||||
@@ -210,6 +212,16 @@ xfs_iformat_fork(
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
/* Check inline dir contents. */
|
||||||
|
if (S_ISDIR(VFS_I(ip)->i_mode) &&
|
||||||
|
dip->di_format == XFS_DINODE_FMT_LOCAL) {
|
||||||
|
error = xfs_dir2_sf_verify(ip);
|
||||||
|
if (error) {
|
||||||
|
xfs_idestroy_fork(ip, XFS_DATA_FORK);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (xfs_is_reflink_inode(ip)) {
|
if (xfs_is_reflink_inode(ip)) {
|
||||||
ASSERT(ip->i_cowfp == NULL);
|
ASSERT(ip->i_cowfp == NULL);
|
||||||
xfs_ifork_init_cow(ip);
|
xfs_ifork_init_cow(ip);
|
||||||
@@ -320,7 +332,6 @@ xfs_iformat_local(
|
|||||||
int whichfork,
|
int whichfork,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the size is unreasonable, then something
|
* If the size is unreasonable, then something
|
||||||
* is wrong and we just bail out rather than crash in
|
* is wrong and we just bail out rather than crash in
|
||||||
|
|||||||
@@ -1629,13 +1629,28 @@ xfs_refcount_recover_cow_leftovers(
|
|||||||
if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
|
if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
|
INIT_LIST_HEAD(&debris);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In this first part, we use an empty transaction to gather up
|
||||||
|
* all the leftover CoW extents so that we can subsequently
|
||||||
|
* delete them. The empty transaction is used to avoid
|
||||||
|
* a buffer lock deadlock if there happens to be a loop in the
|
||||||
|
* refcountbt because we're allowed to re-grab a buffer that is
|
||||||
|
* already attached to our transaction. When we're done
|
||||||
|
* recording the CoW debris we cancel the (empty) transaction
|
||||||
|
* and everything goes away cleanly.
|
||||||
|
*/
|
||||||
|
error = xfs_trans_alloc_empty(mp, &tp);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL);
|
|
||||||
|
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
|
||||||
|
if (error)
|
||||||
|
goto out_trans;
|
||||||
|
cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL);
|
||||||
|
|
||||||
/* Find all the leftover CoW staging extents. */
|
/* Find all the leftover CoW staging extents. */
|
||||||
INIT_LIST_HEAD(&debris);
|
|
||||||
memset(&low, 0, sizeof(low));
|
memset(&low, 0, sizeof(low));
|
||||||
memset(&high, 0, sizeof(high));
|
memset(&high, 0, sizeof(high));
|
||||||
low.rc.rc_startblock = XFS_REFC_COW_START;
|
low.rc.rc_startblock = XFS_REFC_COW_START;
|
||||||
@@ -1645,10 +1660,11 @@ xfs_refcount_recover_cow_leftovers(
|
|||||||
if (error)
|
if (error)
|
||||||
goto out_cursor;
|
goto out_cursor;
|
||||||
xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
|
xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
|
||||||
xfs_buf_relse(agbp);
|
xfs_trans_brelse(tp, agbp);
|
||||||
|
xfs_trans_cancel(tp);
|
||||||
|
|
||||||
/* Now iterate the list to free the leftovers */
|
/* Now iterate the list to free the leftovers */
|
||||||
list_for_each_entry(rr, &debris, rr_list) {
|
list_for_each_entry_safe(rr, n, &debris, rr_list) {
|
||||||
/* Set up transaction. */
|
/* Set up transaction. */
|
||||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
|
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
|
||||||
if (error)
|
if (error)
|
||||||
@@ -1676,8 +1692,16 @@ xfs_refcount_recover_cow_leftovers(
|
|||||||
error = xfs_trans_commit(tp);
|
error = xfs_trans_commit(tp);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
|
list_del(&rr->rr_list);
|
||||||
|
kmem_free(rr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
out_defer:
|
||||||
|
xfs_defer_cancel(&dfops);
|
||||||
|
out_trans:
|
||||||
|
xfs_trans_cancel(tp);
|
||||||
out_free:
|
out_free:
|
||||||
/* Free the leftover list */
|
/* Free the leftover list */
|
||||||
list_for_each_entry_safe(rr, n, &debris, rr_list) {
|
list_for_each_entry_safe(rr, n, &debris, rr_list) {
|
||||||
@@ -1688,11 +1712,6 @@ out_free:
|
|||||||
|
|
||||||
out_cursor:
|
out_cursor:
|
||||||
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
|
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
|
||||||
xfs_buf_relse(agbp);
|
xfs_trans_brelse(tp, agbp);
|
||||||
goto out_free;
|
goto out_trans;
|
||||||
|
|
||||||
out_defer:
|
|
||||||
xfs_defer_cancel(&dfops);
|
|
||||||
xfs_trans_cancel(tp);
|
|
||||||
goto out_free;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,20 @@
|
|||||||
/*
|
/*
|
||||||
* Components of space reservations.
|
* Components of space reservations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Worst case number of rmaps that can be held in a block. */
|
||||||
#define XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) \
|
#define XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) \
|
||||||
(((mp)->m_rmap_mxr[0]) - ((mp)->m_rmap_mnr[0]))
|
(((mp)->m_rmap_mxr[0]) - ((mp)->m_rmap_mnr[0]))
|
||||||
|
|
||||||
|
/* Adding one rmap could split every level up to the top of the tree. */
|
||||||
|
#define XFS_RMAPADD_SPACE_RES(mp) ((mp)->m_rmap_maxlevels)
|
||||||
|
|
||||||
|
/* Blocks we might need to add "b" rmaps to a tree. */
|
||||||
|
#define XFS_NRMAPADD_SPACE_RES(mp, b)\
|
||||||
|
(((b + XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) - 1) / \
|
||||||
|
XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp)) * \
|
||||||
|
XFS_RMAPADD_SPACE_RES(mp))
|
||||||
|
|
||||||
#define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) \
|
#define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) \
|
||||||
(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
|
(((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0]))
|
||||||
#define XFS_EXTENTADD_SPACE_RES(mp,w) (XFS_BM_MAXLEVELS(mp,w) - 1)
|
#define XFS_EXTENTADD_SPACE_RES(mp,w) (XFS_BM_MAXLEVELS(mp,w) - 1)
|
||||||
@@ -30,13 +42,12 @@
|
|||||||
(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
|
(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
|
||||||
XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
|
XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
|
||||||
XFS_EXTENTADD_SPACE_RES(mp,w))
|
XFS_EXTENTADD_SPACE_RES(mp,w))
|
||||||
|
|
||||||
|
/* Blocks we might need to add "b" mappings & rmappings to a file. */
|
||||||
#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
|
#define XFS_SWAP_RMAP_SPACE_RES(mp,b,w)\
|
||||||
(((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \
|
(XFS_NEXTENTADD_SPACE_RES((mp), (b), (w)) + \
|
||||||
XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \
|
XFS_NRMAPADD_SPACE_RES((mp), (b)))
|
||||||
XFS_EXTENTADD_SPACE_RES(mp,w) + \
|
|
||||||
((b + XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) - 1) / \
|
|
||||||
XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp)) * \
|
|
||||||
(mp)->m_rmap_maxlevels)
|
|
||||||
#define XFS_DAENTER_1B(mp,w) \
|
#define XFS_DAENTER_1B(mp,w) \
|
||||||
((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1)
|
((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1)
|
||||||
#define XFS_DAENTER_DBS(mp,w) \
|
#define XFS_DAENTER_DBS(mp,w) \
|
||||||
|
|||||||
+2
-2
@@ -116,11 +116,11 @@ xfs_finish_page_writeback(
|
|||||||
|
|
||||||
bsize = bh->b_size;
|
bsize = bh->b_size;
|
||||||
do {
|
do {
|
||||||
|
if (off > end)
|
||||||
|
break;
|
||||||
next = bh->b_this_page;
|
next = bh->b_this_page;
|
||||||
if (off < bvec->bv_offset)
|
if (off < bvec->bv_offset)
|
||||||
goto next_bh;
|
goto next_bh;
|
||||||
if (off > end)
|
|
||||||
break;
|
|
||||||
bh->b_end_io(bh, !error);
|
bh->b_end_io(bh, !error);
|
||||||
next_bh:
|
next_bh:
|
||||||
off += bsize;
|
off += bsize;
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
#include "xfs_bmap.h"
|
#include "xfs_bmap.h"
|
||||||
#include "xfs_icache.h"
|
#include "xfs_icache.h"
|
||||||
#include "xfs_trace.h"
|
#include "xfs_trace.h"
|
||||||
|
#include "xfs_bmap_btree.h"
|
||||||
|
#include "xfs_trans_space.h"
|
||||||
|
|
||||||
|
|
||||||
kmem_zone_t *xfs_bui_zone;
|
kmem_zone_t *xfs_bui_zone;
|
||||||
@@ -446,7 +448,8 @@ xfs_bui_recover(
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
|
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,
|
||||||
|
XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
budp = xfs_trans_get_bud(tp, buip);
|
budp = xfs_trans_get_bud(tp, buip);
|
||||||
|
|||||||
+10
-8
@@ -588,9 +588,13 @@ xfs_getbmap(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
/* Local format data forks report no extents. */
|
||||||
|
if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
|
||||||
|
bmv->bmv_entries = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
|
if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
|
||||||
ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
|
ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
|
||||||
ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (xfs_get_extsz_hint(ip) ||
|
if (xfs_get_extsz_hint(ip) ||
|
||||||
@@ -718,7 +722,7 @@ xfs_getbmap(
|
|||||||
* extents.
|
* extents.
|
||||||
*/
|
*/
|
||||||
if (map[i].br_startblock == DELAYSTARTBLOCK &&
|
if (map[i].br_startblock == DELAYSTARTBLOCK &&
|
||||||
map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
|
map[i].br_startoff < XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
|
||||||
ASSERT((iflags & BMV_IF_DELALLOC) != 0);
|
ASSERT((iflags & BMV_IF_DELALLOC) != 0);
|
||||||
|
|
||||||
if (map[i].br_startblock == HOLESTARTBLOCK &&
|
if (map[i].br_startblock == HOLESTARTBLOCK &&
|
||||||
@@ -911,9 +915,9 @@ xfs_can_free_eofblocks(struct xfs_inode *ip, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called by xfs_inactive to free any blocks beyond eof
|
* This is called to free any blocks beyond eof. The caller must hold
|
||||||
* when the link count isn't zero and by xfs_dm_punch_hole() when
|
* IOLOCK_EXCL unless we are in the inode reclaim path and have the only
|
||||||
* punching a hole to EOF.
|
* reference to the inode.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xfs_free_eofblocks(
|
xfs_free_eofblocks(
|
||||||
@@ -928,8 +932,6 @@ xfs_free_eofblocks(
|
|||||||
struct xfs_bmbt_irec imap;
|
struct xfs_bmbt_irec imap;
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
|
|
||||||
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out if there are any blocks beyond the end
|
* Figure out if there are any blocks beyond the end
|
||||||
* of the file. If not, then there is nothing to do.
|
* of the file. If not, then there is nothing to do.
|
||||||
|
|||||||
+50
-12
@@ -96,27 +96,41 @@ static inline void
|
|||||||
xfs_buf_ioacct_inc(
|
xfs_buf_ioacct_inc(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
if (bp->b_flags & (XBF_NO_IOACCT|_XBF_IN_FLIGHT))
|
if (bp->b_flags & XBF_NO_IOACCT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ASSERT(bp->b_flags & XBF_ASYNC);
|
ASSERT(bp->b_flags & XBF_ASYNC);
|
||||||
bp->b_flags |= _XBF_IN_FLIGHT;
|
spin_lock(&bp->b_lock);
|
||||||
percpu_counter_inc(&bp->b_target->bt_io_count);
|
if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) {
|
||||||
|
bp->b_state |= XFS_BSTATE_IN_FLIGHT;
|
||||||
|
percpu_counter_inc(&bp->b_target->bt_io_count);
|
||||||
|
}
|
||||||
|
spin_unlock(&bp->b_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear the in-flight state on a buffer about to be released to the LRU or
|
* Clear the in-flight state on a buffer about to be released to the LRU or
|
||||||
* freed and unaccount from the buftarg.
|
* freed and unaccount from the buftarg.
|
||||||
*/
|
*/
|
||||||
|
static inline void
|
||||||
|
__xfs_buf_ioacct_dec(
|
||||||
|
struct xfs_buf *bp)
|
||||||
|
{
|
||||||
|
ASSERT(spin_is_locked(&bp->b_lock));
|
||||||
|
|
||||||
|
if (bp->b_state & XFS_BSTATE_IN_FLIGHT) {
|
||||||
|
bp->b_state &= ~XFS_BSTATE_IN_FLIGHT;
|
||||||
|
percpu_counter_dec(&bp->b_target->bt_io_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
xfs_buf_ioacct_dec(
|
xfs_buf_ioacct_dec(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
if (!(bp->b_flags & _XBF_IN_FLIGHT))
|
spin_lock(&bp->b_lock);
|
||||||
return;
|
__xfs_buf_ioacct_dec(bp);
|
||||||
|
spin_unlock(&bp->b_lock);
|
||||||
bp->b_flags &= ~_XBF_IN_FLIGHT;
|
|
||||||
percpu_counter_dec(&bp->b_target->bt_io_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -148,9 +162,9 @@ xfs_buf_stale(
|
|||||||
* unaccounted (released to LRU) before that occurs. Drop in-flight
|
* unaccounted (released to LRU) before that occurs. Drop in-flight
|
||||||
* status now to preserve accounting consistency.
|
* status now to preserve accounting consistency.
|
||||||
*/
|
*/
|
||||||
xfs_buf_ioacct_dec(bp);
|
|
||||||
|
|
||||||
spin_lock(&bp->b_lock);
|
spin_lock(&bp->b_lock);
|
||||||
|
__xfs_buf_ioacct_dec(bp);
|
||||||
|
|
||||||
atomic_set(&bp->b_lru_ref, 0);
|
atomic_set(&bp->b_lru_ref, 0);
|
||||||
if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
|
if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
|
||||||
(list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
|
(list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
|
||||||
@@ -953,12 +967,12 @@ xfs_buf_rele(
|
|||||||
* ensures the decrement occurs only once per-buf.
|
* ensures the decrement occurs only once per-buf.
|
||||||
*/
|
*/
|
||||||
if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
|
if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
|
||||||
xfs_buf_ioacct_dec(bp);
|
__xfs_buf_ioacct_dec(bp);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the last reference has been dropped ... */
|
/* the last reference has been dropped ... */
|
||||||
xfs_buf_ioacct_dec(bp);
|
__xfs_buf_ioacct_dec(bp);
|
||||||
if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
|
if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
|
||||||
/*
|
/*
|
||||||
* If the buffer is added to the LRU take a new reference to the
|
* If the buffer is added to the LRU take a new reference to the
|
||||||
@@ -1052,6 +1066,8 @@ void
|
|||||||
xfs_buf_unlock(
|
xfs_buf_unlock(
|
||||||
struct xfs_buf *bp)
|
struct xfs_buf *bp)
|
||||||
{
|
{
|
||||||
|
ASSERT(xfs_buf_islocked(bp));
|
||||||
|
|
||||||
XB_CLEAR_OWNER(bp);
|
XB_CLEAR_OWNER(bp);
|
||||||
up(&bp->b_sema);
|
up(&bp->b_sema);
|
||||||
|
|
||||||
@@ -1789,6 +1805,28 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cancel a delayed write list.
|
||||||
|
*
|
||||||
|
* Remove each buffer from the list, clear the delwri queue flag and drop the
|
||||||
|
* associated buffer reference.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xfs_buf_delwri_cancel(
|
||||||
|
struct list_head *list)
|
||||||
|
{
|
||||||
|
struct xfs_buf *bp;
|
||||||
|
|
||||||
|
while (!list_empty(list)) {
|
||||||
|
bp = list_first_entry(list, struct xfs_buf, b_list);
|
||||||
|
|
||||||
|
xfs_buf_lock(bp);
|
||||||
|
bp->b_flags &= ~_XBF_DELWRI_Q;
|
||||||
|
list_del_init(&bp->b_list);
|
||||||
|
xfs_buf_relse(bp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a buffer to the delayed write list.
|
* Add a buffer to the delayed write list.
|
||||||
*
|
*
|
||||||
|
|||||||
+3
-3
@@ -63,7 +63,6 @@ typedef enum {
|
|||||||
#define _XBF_KMEM (1 << 21)/* backed by heap memory */
|
#define _XBF_KMEM (1 << 21)/* backed by heap memory */
|
||||||
#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
|
#define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */
|
||||||
#define _XBF_COMPOUND (1 << 23)/* compound buffer */
|
#define _XBF_COMPOUND (1 << 23)/* compound buffer */
|
||||||
#define _XBF_IN_FLIGHT (1 << 25) /* I/O in flight, for accounting purposes */
|
|
||||||
|
|
||||||
typedef unsigned int xfs_buf_flags_t;
|
typedef unsigned int xfs_buf_flags_t;
|
||||||
|
|
||||||
@@ -83,14 +82,14 @@ typedef unsigned int xfs_buf_flags_t;
|
|||||||
{ _XBF_PAGES, "PAGES" }, \
|
{ _XBF_PAGES, "PAGES" }, \
|
||||||
{ _XBF_KMEM, "KMEM" }, \
|
{ _XBF_KMEM, "KMEM" }, \
|
||||||
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
|
{ _XBF_DELWRI_Q, "DELWRI_Q" }, \
|
||||||
{ _XBF_COMPOUND, "COMPOUND" }, \
|
{ _XBF_COMPOUND, "COMPOUND" }
|
||||||
{ _XBF_IN_FLIGHT, "IN_FLIGHT" }
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal state flags.
|
* Internal state flags.
|
||||||
*/
|
*/
|
||||||
#define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */
|
#define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */
|
||||||
|
#define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The xfs_buftarg contains 2 notions of "sector size" -
|
* The xfs_buftarg contains 2 notions of "sector size" -
|
||||||
@@ -330,6 +329,7 @@ extern void *xfs_buf_offset(struct xfs_buf *, size_t);
|
|||||||
extern void xfs_buf_stale(struct xfs_buf *bp);
|
extern void xfs_buf_stale(struct xfs_buf *bp);
|
||||||
|
|
||||||
/* Delayed Write Buffer Routines */
|
/* Delayed Write Buffer Routines */
|
||||||
|
extern void xfs_buf_delwri_cancel(struct list_head *);
|
||||||
extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
|
extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
|
||||||
extern int xfs_buf_delwri_submit(struct list_head *);
|
extern int xfs_buf_delwri_submit(struct list_head *);
|
||||||
extern int xfs_buf_delwri_submit_nowait(struct list_head *);
|
extern int xfs_buf_delwri_submit_nowait(struct list_head *);
|
||||||
|
|||||||
+11
-15
@@ -71,22 +71,11 @@ xfs_dir2_sf_getdents(
|
|||||||
struct xfs_da_geometry *geo = args->geo;
|
struct xfs_da_geometry *geo = args->geo;
|
||||||
|
|
||||||
ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
|
ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
|
||||||
/*
|
|
||||||
* Give up if the directory is way too short.
|
|
||||||
*/
|
|
||||||
if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
|
|
||||||
ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
|
||||||
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
ASSERT(dp->i_df.if_u1.if_data != NULL);
|
||||||
|
|
||||||
sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
|
sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
|
||||||
|
|
||||||
if (dp->i_d.di_size < xfs_dir2_sf_hdr_size(sfp->i8count))
|
|
||||||
return -EFSCORRUPTED;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the block number in the offset is out of range, we're done.
|
* If the block number in the offset is out of range, we're done.
|
||||||
*/
|
*/
|
||||||
@@ -405,6 +394,7 @@ xfs_dir2_leaf_readbuf(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Do we need more readahead?
|
* Do we need more readahead?
|
||||||
|
* Each loop tries to process 1 full dir blk; last may be partial.
|
||||||
*/
|
*/
|
||||||
blk_start_plug(&plug);
|
blk_start_plug(&plug);
|
||||||
for (mip->ra_index = mip->ra_offset = i = 0;
|
for (mip->ra_index = mip->ra_offset = i = 0;
|
||||||
@@ -415,7 +405,8 @@ xfs_dir2_leaf_readbuf(
|
|||||||
* Read-ahead a contiguous directory block.
|
* Read-ahead a contiguous directory block.
|
||||||
*/
|
*/
|
||||||
if (i > mip->ra_current &&
|
if (i > mip->ra_current &&
|
||||||
map[mip->ra_index].br_blockcount >= geo->fsbcount) {
|
(map[mip->ra_index].br_blockcount - mip->ra_offset) >=
|
||||||
|
geo->fsbcount) {
|
||||||
xfs_dir3_data_readahead(dp,
|
xfs_dir3_data_readahead(dp,
|
||||||
map[mip->ra_index].br_startoff + mip->ra_offset,
|
map[mip->ra_index].br_startoff + mip->ra_offset,
|
||||||
XFS_FSB_TO_DADDR(dp->i_mount,
|
XFS_FSB_TO_DADDR(dp->i_mount,
|
||||||
@@ -436,14 +427,19 @@ xfs_dir2_leaf_readbuf(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Advance offset through the mapping table.
|
* Advance offset through the mapping table, processing a full
|
||||||
|
* dir block even if it is fragmented into several extents.
|
||||||
|
* But stop if we have consumed all valid mappings, even if
|
||||||
|
* it's not yet a full directory block.
|
||||||
*/
|
*/
|
||||||
for (j = 0; j < geo->fsbcount; j += length ) {
|
for (j = 0;
|
||||||
|
j < geo->fsbcount && mip->ra_index < mip->map_valid;
|
||||||
|
j += length ) {
|
||||||
/*
|
/*
|
||||||
* The rest of this extent but not more than a dir
|
* The rest of this extent but not more than a dir
|
||||||
* block.
|
* block.
|
||||||
*/
|
*/
|
||||||
length = min_t(int, geo->fsbcount,
|
length = min_t(int, geo->fsbcount - j,
|
||||||
map[mip->ra_index].br_blockcount -
|
map[mip->ra_index].br_blockcount -
|
||||||
mip->ra_offset);
|
mip->ra_offset);
|
||||||
mip->ra_offset += length;
|
mip->ra_offset += length;
|
||||||
|
|||||||
+11
-22
@@ -1130,13 +1130,13 @@ xfs_find_get_desired_pgoff(
|
|||||||
|
|
||||||
index = startoff >> PAGE_SHIFT;
|
index = startoff >> PAGE_SHIFT;
|
||||||
endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
|
endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
|
||||||
end = endoff >> PAGE_SHIFT;
|
end = (endoff - 1) >> PAGE_SHIFT;
|
||||||
do {
|
do {
|
||||||
int want;
|
int want;
|
||||||
unsigned nr_pages;
|
unsigned nr_pages;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
want = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
|
want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
|
||||||
nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
|
nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
|
||||||
want);
|
want);
|
||||||
/*
|
/*
|
||||||
@@ -1163,17 +1163,6 @@ xfs_find_get_desired_pgoff(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* At lease we found one page. If this is the first time we
|
|
||||||
* step into the loop, and if the first page index offset is
|
|
||||||
* greater than the given search offset, a hole was found.
|
|
||||||
*/
|
|
||||||
if (type == HOLE_OFF && lastoff == startoff &&
|
|
||||||
lastoff < page_offset(pvec.pages[0])) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nr_pages; i++) {
|
for (i = 0; i < nr_pages; i++) {
|
||||||
struct page *page = pvec.pages[i];
|
struct page *page = pvec.pages[i];
|
||||||
loff_t b_offset;
|
loff_t b_offset;
|
||||||
@@ -1185,18 +1174,18 @@ xfs_find_get_desired_pgoff(
|
|||||||
* file mapping. However, page->index will not change
|
* file mapping. However, page->index will not change
|
||||||
* because we have a reference on the page.
|
* because we have a reference on the page.
|
||||||
*
|
*
|
||||||
* Searching done if the page index is out of range.
|
* If current page offset is beyond where we've ended,
|
||||||
* If the current offset is not reaches the end of
|
* we've found a hole.
|
||||||
* the specified search range, there should be a hole
|
|
||||||
* between them.
|
|
||||||
*/
|
*/
|
||||||
if (page->index > end) {
|
if (type == HOLE_OFF && lastoff < endoff &&
|
||||||
if (type == HOLE_OFF && lastoff < endoff) {
|
lastoff < page_offset(pvec.pages[i])) {
|
||||||
*offset = lastoff;
|
found = true;
|
||||||
found = true;
|
*offset = lastoff;
|
||||||
}
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* Searching done if the page index is out of range. */
|
||||||
|
if (page->index > end)
|
||||||
|
goto out;
|
||||||
|
|
||||||
lock_page(page);
|
lock_page(page);
|
||||||
/*
|
/*
|
||||||
|
|||||||
+49
-9
@@ -264,6 +264,22 @@ xfs_inode_clear_reclaim_tag(
|
|||||||
xfs_perag_clear_reclaim_tag(pag);
|
xfs_perag_clear_reclaim_tag(pag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xfs_inew_wait(
|
||||||
|
struct xfs_inode *ip)
|
||||||
|
{
|
||||||
|
wait_queue_head_t *wq = bit_waitqueue(&ip->i_flags, __XFS_INEW_BIT);
|
||||||
|
DEFINE_WAIT_BIT(wait, &ip->i_flags, __XFS_INEW_BIT);
|
||||||
|
|
||||||
|
do {
|
||||||
|
prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
|
||||||
|
if (!xfs_iflags_test(ip, XFS_INEW))
|
||||||
|
break;
|
||||||
|
schedule();
|
||||||
|
} while (true);
|
||||||
|
finish_wait(wq, &wait.wait);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When we recycle a reclaimable inode, we need to re-initialise the VFS inode
|
* When we recycle a reclaimable inode, we need to re-initialise the VFS inode
|
||||||
* part of the structure. This is made more complex by the fact we store
|
* part of the structure. This is made more complex by the fact we store
|
||||||
@@ -368,14 +384,17 @@ xfs_iget_cache_hit(
|
|||||||
|
|
||||||
error = xfs_reinit_inode(mp, inode);
|
error = xfs_reinit_inode(mp, inode);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
bool wake;
|
||||||
/*
|
/*
|
||||||
* Re-initializing the inode failed, and we are in deep
|
* Re-initializing the inode failed, and we are in deep
|
||||||
* trouble. Try to re-add it to the reclaim list.
|
* trouble. Try to re-add it to the reclaim list.
|
||||||
*/
|
*/
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
spin_lock(&ip->i_flags_lock);
|
spin_lock(&ip->i_flags_lock);
|
||||||
|
wake = !!__xfs_iflags_test(ip, XFS_INEW);
|
||||||
ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
|
ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
|
||||||
|
if (wake)
|
||||||
|
wake_up_bit(&ip->i_flags, __XFS_INEW_BIT);
|
||||||
ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
|
ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
|
||||||
trace_xfs_iget_reclaim_fail(ip);
|
trace_xfs_iget_reclaim_fail(ip);
|
||||||
goto out_error;
|
goto out_error;
|
||||||
@@ -625,9 +644,11 @@ out_error_or_again:
|
|||||||
|
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_inode_ag_walk_grab(
|
xfs_inode_ag_walk_grab(
|
||||||
struct xfs_inode *ip)
|
struct xfs_inode *ip,
|
||||||
|
int flags)
|
||||||
{
|
{
|
||||||
struct inode *inode = VFS_I(ip);
|
struct inode *inode = VFS_I(ip);
|
||||||
|
bool newinos = !!(flags & XFS_AGITER_INEW_WAIT);
|
||||||
|
|
||||||
ASSERT(rcu_read_lock_held());
|
ASSERT(rcu_read_lock_held());
|
||||||
|
|
||||||
@@ -645,7 +666,8 @@ xfs_inode_ag_walk_grab(
|
|||||||
goto out_unlock_noent;
|
goto out_unlock_noent;
|
||||||
|
|
||||||
/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
|
/* avoid new or reclaimable inodes. Leave for reclaim code to flush */
|
||||||
if (__xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIMABLE | XFS_IRECLAIM))
|
if ((!newinos && __xfs_iflags_test(ip, XFS_INEW)) ||
|
||||||
|
__xfs_iflags_test(ip, XFS_IRECLAIMABLE | XFS_IRECLAIM))
|
||||||
goto out_unlock_noent;
|
goto out_unlock_noent;
|
||||||
spin_unlock(&ip->i_flags_lock);
|
spin_unlock(&ip->i_flags_lock);
|
||||||
|
|
||||||
@@ -673,7 +695,8 @@ xfs_inode_ag_walk(
|
|||||||
void *args),
|
void *args),
|
||||||
int flags,
|
int flags,
|
||||||
void *args,
|
void *args,
|
||||||
int tag)
|
int tag,
|
||||||
|
int iter_flags)
|
||||||
{
|
{
|
||||||
uint32_t first_index;
|
uint32_t first_index;
|
||||||
int last_error = 0;
|
int last_error = 0;
|
||||||
@@ -715,7 +738,7 @@ restart:
|
|||||||
for (i = 0; i < nr_found; i++) {
|
for (i = 0; i < nr_found; i++) {
|
||||||
struct xfs_inode *ip = batch[i];
|
struct xfs_inode *ip = batch[i];
|
||||||
|
|
||||||
if (done || xfs_inode_ag_walk_grab(ip))
|
if (done || xfs_inode_ag_walk_grab(ip, iter_flags))
|
||||||
batch[i] = NULL;
|
batch[i] = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -743,6 +766,9 @@ restart:
|
|||||||
for (i = 0; i < nr_found; i++) {
|
for (i = 0; i < nr_found; i++) {
|
||||||
if (!batch[i])
|
if (!batch[i])
|
||||||
continue;
|
continue;
|
||||||
|
if ((iter_flags & XFS_AGITER_INEW_WAIT) &&
|
||||||
|
xfs_iflags_test(batch[i], XFS_INEW))
|
||||||
|
xfs_inew_wait(batch[i]);
|
||||||
error = execute(batch[i], flags, args);
|
error = execute(batch[i], flags, args);
|
||||||
IRELE(batch[i]);
|
IRELE(batch[i]);
|
||||||
if (error == -EAGAIN) {
|
if (error == -EAGAIN) {
|
||||||
@@ -822,12 +848,13 @@ xfs_cowblocks_worker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_inode_ag_iterator(
|
xfs_inode_ag_iterator_flags(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
int (*execute)(struct xfs_inode *ip, int flags,
|
int (*execute)(struct xfs_inode *ip, int flags,
|
||||||
void *args),
|
void *args),
|
||||||
int flags,
|
int flags,
|
||||||
void *args)
|
void *args,
|
||||||
|
int iter_flags)
|
||||||
{
|
{
|
||||||
struct xfs_perag *pag;
|
struct xfs_perag *pag;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@@ -837,7 +864,8 @@ xfs_inode_ag_iterator(
|
|||||||
ag = 0;
|
ag = 0;
|
||||||
while ((pag = xfs_perag_get(mp, ag))) {
|
while ((pag = xfs_perag_get(mp, ag))) {
|
||||||
ag = pag->pag_agno + 1;
|
ag = pag->pag_agno + 1;
|
||||||
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1);
|
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, -1,
|
||||||
|
iter_flags);
|
||||||
xfs_perag_put(pag);
|
xfs_perag_put(pag);
|
||||||
if (error) {
|
if (error) {
|
||||||
last_error = error;
|
last_error = error;
|
||||||
@@ -848,6 +876,17 @@ xfs_inode_ag_iterator(
|
|||||||
return last_error;
|
return last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xfs_inode_ag_iterator(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
int (*execute)(struct xfs_inode *ip, int flags,
|
||||||
|
void *args),
|
||||||
|
int flags,
|
||||||
|
void *args)
|
||||||
|
{
|
||||||
|
return xfs_inode_ag_iterator_flags(mp, execute, flags, args, 0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_inode_ag_iterator_tag(
|
xfs_inode_ag_iterator_tag(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
@@ -865,7 +904,8 @@ xfs_inode_ag_iterator_tag(
|
|||||||
ag = 0;
|
ag = 0;
|
||||||
while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
|
while ((pag = xfs_perag_get_tag(mp, ag, tag))) {
|
||||||
ag = pag->pag_agno + 1;
|
ag = pag->pag_agno + 1;
|
||||||
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag);
|
error = xfs_inode_ag_walk(mp, pag, execute, flags, args, tag,
|
||||||
|
0);
|
||||||
xfs_perag_put(pag);
|
xfs_perag_put(pag);
|
||||||
if (error) {
|
if (error) {
|
||||||
last_error = error;
|
last_error = error;
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ struct xfs_eofblocks {
|
|||||||
#define XFS_IGET_UNTRUSTED 0x2
|
#define XFS_IGET_UNTRUSTED 0x2
|
||||||
#define XFS_IGET_DONTCACHE 0x4
|
#define XFS_IGET_DONTCACHE 0x4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* flags for AG inode iterator
|
||||||
|
*/
|
||||||
|
#define XFS_AGITER_INEW_WAIT 0x1 /* wait on new inodes */
|
||||||
|
|
||||||
int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
|
int xfs_iget(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t ino,
|
||||||
uint flags, uint lock_flags, xfs_inode_t **ipp);
|
uint flags, uint lock_flags, xfs_inode_t **ipp);
|
||||||
|
|
||||||
@@ -79,6 +84,9 @@ void xfs_cowblocks_worker(struct work_struct *);
|
|||||||
int xfs_inode_ag_iterator(struct xfs_mount *mp,
|
int xfs_inode_ag_iterator(struct xfs_mount *mp,
|
||||||
int (*execute)(struct xfs_inode *ip, int flags, void *args),
|
int (*execute)(struct xfs_inode *ip, int flags, void *args),
|
||||||
int flags, void *args);
|
int flags, void *args);
|
||||||
|
int xfs_inode_ag_iterator_flags(struct xfs_mount *mp,
|
||||||
|
int (*execute)(struct xfs_inode *ip, int flags, void *args),
|
||||||
|
int flags, void *args, int iter_flags);
|
||||||
int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
|
int xfs_inode_ag_iterator_tag(struct xfs_mount *mp,
|
||||||
int (*execute)(struct xfs_inode *ip, int flags, void *args),
|
int (*execute)(struct xfs_inode *ip, int flags, void *args),
|
||||||
int flags, void *args, int tag);
|
int flags, void *args, int tag);
|
||||||
|
|||||||
+12
-4
@@ -50,6 +50,7 @@
|
|||||||
#include "xfs_log.h"
|
#include "xfs_log.h"
|
||||||
#include "xfs_bmap_btree.h"
|
#include "xfs_bmap_btree.h"
|
||||||
#include "xfs_reflink.h"
|
#include "xfs_reflink.h"
|
||||||
|
#include "xfs_dir2_priv.h"
|
||||||
|
|
||||||
kmem_zone_t *xfs_inode_zone;
|
kmem_zone_t *xfs_inode_zone;
|
||||||
|
|
||||||
@@ -1914,12 +1915,13 @@ xfs_inactive(
|
|||||||
* force is true because we are evicting an inode from the
|
* force is true because we are evicting an inode from the
|
||||||
* cache. Post-eof blocks must be freed, lest we end up with
|
* cache. Post-eof blocks must be freed, lest we end up with
|
||||||
* broken free space accounting.
|
* broken free space accounting.
|
||||||
|
*
|
||||||
|
* Note: don't bother with iolock here since lockdep complains
|
||||||
|
* about acquiring it in reclaim context. We have the only
|
||||||
|
* reference to the inode at this point anyways.
|
||||||
*/
|
*/
|
||||||
if (xfs_can_free_eofblocks(ip, true)) {
|
if (xfs_can_free_eofblocks(ip, true))
|
||||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
|
||||||
xfs_free_eofblocks(ip);
|
xfs_free_eofblocks(ip);
|
||||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3562,6 +3564,12 @@ xfs_iflush_int(
|
|||||||
if (ip->i_d.di_version < 3)
|
if (ip->i_d.di_version < 3)
|
||||||
ip->i_d.di_flushiter++;
|
ip->i_d.di_flushiter++;
|
||||||
|
|
||||||
|
/* Check the inline directory data. */
|
||||||
|
if (S_ISDIR(VFS_I(ip)->i_mode) &&
|
||||||
|
ip->i_d.di_format == XFS_DINODE_FMT_LOCAL &&
|
||||||
|
xfs_dir2_sf_verify(ip))
|
||||||
|
goto corrupt_out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the dirty parts of the inode into the on-disk inode. We always
|
* Copy the dirty parts of the inode into the on-disk inode. We always
|
||||||
* copy out the core of the inode, because if the inode is dirty at all
|
* copy out the core of the inode, because if the inode is dirty at all
|
||||||
|
|||||||
+3
-1
@@ -217,7 +217,8 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
|
|||||||
#define XFS_IRECLAIM (1 << 0) /* started reclaiming this inode */
|
#define XFS_IRECLAIM (1 << 0) /* started reclaiming this inode */
|
||||||
#define XFS_ISTALE (1 << 1) /* inode has been staled */
|
#define XFS_ISTALE (1 << 1) /* inode has been staled */
|
||||||
#define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */
|
#define XFS_IRECLAIMABLE (1 << 2) /* inode can be reclaimed */
|
||||||
#define XFS_INEW (1 << 3) /* inode has just been allocated */
|
#define __XFS_INEW_BIT 3 /* inode has just been allocated */
|
||||||
|
#define XFS_INEW (1 << __XFS_INEW_BIT)
|
||||||
#define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */
|
#define XFS_ITRUNCATED (1 << 5) /* truncated down so flush-on-close */
|
||||||
#define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */
|
#define XFS_IDIRTY_RELEASE (1 << 6) /* dirty release already seen */
|
||||||
#define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */
|
#define __XFS_IFLOCK_BIT 7 /* inode is being flushed right now */
|
||||||
@@ -467,6 +468,7 @@ static inline void xfs_finish_inode_setup(struct xfs_inode *ip)
|
|||||||
xfs_iflags_clear(ip, XFS_INEW);
|
xfs_iflags_clear(ip, XFS_INEW);
|
||||||
barrier();
|
barrier();
|
||||||
unlock_new_inode(VFS_I(ip));
|
unlock_new_inode(VFS_I(ip));
|
||||||
|
wake_up_bit(&ip->i_flags, __XFS_INEW_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
|
static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
|
||||||
|
|||||||
+3
-2
@@ -1542,10 +1542,11 @@ xfs_ioc_getbmap(
|
|||||||
unsigned int cmd,
|
unsigned int cmd,
|
||||||
void __user *arg)
|
void __user *arg)
|
||||||
{
|
{
|
||||||
struct getbmapx bmx;
|
struct getbmapx bmx = { 0 };
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (copy_from_user(&bmx, arg, sizeof(struct getbmapx)))
|
/* struct getbmap is a strict subset of struct getbmapx. */
|
||||||
|
if (copy_from_user(&bmx, arg, offsetof(struct getbmapx, bmv_iflags)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (bmx.bmv_count < 2)
|
if (bmx.bmv_count < 2)
|
||||||
|
|||||||
+2
-2
@@ -1151,10 +1151,10 @@ xfs_xattr_iomap_begin(
|
|||||||
if (XFS_FORCED_SHUTDOWN(mp))
|
if (XFS_FORCED_SHUTDOWN(mp))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
lockmode = xfs_ilock_data_map_shared(ip);
|
lockmode = xfs_ilock_attr_map_shared(ip);
|
||||||
|
|
||||||
/* if there are no attribute fork or extents, return ENOENT */
|
/* if there are no attribute fork or extents, return ENOENT */
|
||||||
if (XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
|
if (!XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
|
||||||
error = -ENOENT;
|
error = -ENOENT;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -585,7 +585,7 @@ xfs_inumbers(
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
|
bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
|
||||||
buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
|
buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP);
|
||||||
do {
|
do {
|
||||||
struct xfs_inobt_rec_incore r;
|
struct xfs_inobt_rec_incore r;
|
||||||
int stat;
|
int stat;
|
||||||
|
|||||||
+1
-1
@@ -1293,7 +1293,7 @@ void
|
|||||||
xfs_log_work_queue(
|
xfs_log_work_queue(
|
||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
queue_delayed_work(mp->m_log_workqueue, &mp->m_log->l_work,
|
queue_delayed_work(mp->m_sync_workqueue, &mp->m_log->l_work,
|
||||||
msecs_to_jiffies(xfs_syncd_centisecs * 10));
|
msecs_to_jiffies(xfs_syncd_centisecs * 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ typedef struct xfs_mount {
|
|||||||
struct workqueue_struct *m_reclaim_workqueue;
|
struct workqueue_struct *m_reclaim_workqueue;
|
||||||
struct workqueue_struct *m_log_workqueue;
|
struct workqueue_struct *m_log_workqueue;
|
||||||
struct workqueue_struct *m_eofblocks_workqueue;
|
struct workqueue_struct *m_eofblocks_workqueue;
|
||||||
|
struct workqueue_struct *m_sync_workqueue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generation of the filesysyem layout. This is incremented by each
|
* Generation of the filesysyem layout. This is incremented by each
|
||||||
|
|||||||
+1
-6
@@ -1384,12 +1384,7 @@ xfs_qm_quotacheck(
|
|||||||
mp->m_qflags |= flags;
|
mp->m_qflags |= flags;
|
||||||
|
|
||||||
error_return:
|
error_return:
|
||||||
while (!list_empty(&buffer_list)) {
|
xfs_buf_delwri_cancel(&buffer_list);
|
||||||
struct xfs_buf *bp =
|
|
||||||
list_first_entry(&buffer_list, struct xfs_buf, b_list);
|
|
||||||
list_del_init(&bp->b_list);
|
|
||||||
xfs_buf_relse(bp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
xfs_warn(mp,
|
xfs_warn(mp,
|
||||||
|
|||||||
@@ -759,5 +759,6 @@ xfs_qm_dqrele_all_inodes(
|
|||||||
uint flags)
|
uint flags)
|
||||||
{
|
{
|
||||||
ASSERT(mp->m_quotainfo);
|
ASSERT(mp->m_quotainfo);
|
||||||
xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
|
xfs_inode_ag_iterator_flags(mp, xfs_dqrele_inode, flags, NULL,
|
||||||
|
XFS_AGITER_INEW_WAIT);
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-2
@@ -736,8 +736,22 @@ xfs_reflink_end_cow(
|
|||||||
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
|
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
|
||||||
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
|
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
|
||||||
|
|
||||||
/* Start a rolling transaction to switch the mappings */
|
/*
|
||||||
resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
|
* Start a rolling transaction to switch the mappings. We're
|
||||||
|
* unlikely ever to have to remap 16T worth of single-block
|
||||||
|
* extents, so just cap the worst case extent count to 2^32-1.
|
||||||
|
* Stick a warning in just in case, and avoid 64-bit division.
|
||||||
|
*/
|
||||||
|
BUILD_BUG_ON(MAX_RW_COUNT > UINT_MAX);
|
||||||
|
if (end_fsb - offset_fsb > UINT_MAX) {
|
||||||
|
error = -EFSCORRUPTED;
|
||||||
|
xfs_force_shutdown(ip->i_mount, SHUTDOWN_CORRUPT_INCORE);
|
||||||
|
ASSERT(0);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
resblks = XFS_NEXTENTADD_SPACE_RES(ip->i_mount,
|
||||||
|
(unsigned int)(end_fsb - offset_fsb),
|
||||||
|
XFS_DATA_FORK);
|
||||||
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write,
|
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write,
|
||||||
resblks, 0, 0, &tp);
|
resblks, 0, 0, &tp);
|
||||||
if (error)
|
if (error)
|
||||||
|
|||||||
@@ -872,8 +872,15 @@ xfs_init_mount_workqueues(
|
|||||||
if (!mp->m_eofblocks_workqueue)
|
if (!mp->m_eofblocks_workqueue)
|
||||||
goto out_destroy_log;
|
goto out_destroy_log;
|
||||||
|
|
||||||
|
mp->m_sync_workqueue = alloc_workqueue("xfs-sync/%s", WQ_FREEZABLE, 0,
|
||||||
|
mp->m_fsname);
|
||||||
|
if (!mp->m_sync_workqueue)
|
||||||
|
goto out_destroy_eofb;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_destroy_eofb:
|
||||||
|
destroy_workqueue(mp->m_eofblocks_workqueue);
|
||||||
out_destroy_log:
|
out_destroy_log:
|
||||||
destroy_workqueue(mp->m_log_workqueue);
|
destroy_workqueue(mp->m_log_workqueue);
|
||||||
out_destroy_reclaim:
|
out_destroy_reclaim:
|
||||||
@@ -894,6 +901,7 @@ STATIC void
|
|||||||
xfs_destroy_mount_workqueues(
|
xfs_destroy_mount_workqueues(
|
||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
|
destroy_workqueue(mp->m_sync_workqueue);
|
||||||
destroy_workqueue(mp->m_eofblocks_workqueue);
|
destroy_workqueue(mp->m_eofblocks_workqueue);
|
||||||
destroy_workqueue(mp->m_log_workqueue);
|
destroy_workqueue(mp->m_log_workqueue);
|
||||||
destroy_workqueue(mp->m_reclaim_workqueue);
|
destroy_workqueue(mp->m_reclaim_workqueue);
|
||||||
|
|||||||
@@ -262,6 +262,28 @@ xfs_trans_alloc(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an empty transaction with no reservation. This is a defensive
|
||||||
|
* mechanism for routines that query metadata without actually modifying
|
||||||
|
* them -- if the metadata being queried is somehow cross-linked (think a
|
||||||
|
* btree block pointer that points higher in the tree), we risk deadlock.
|
||||||
|
* However, blocks grabbed as part of a transaction can be re-grabbed.
|
||||||
|
* The verifiers will notice the corrupt block and the operation will fail
|
||||||
|
* back to userspace without deadlocking.
|
||||||
|
*
|
||||||
|
* Note the zero-length reservation; this transaction MUST be cancelled
|
||||||
|
* without any dirty data.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xfs_trans_alloc_empty(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
struct xfs_trans **tpp)
|
||||||
|
{
|
||||||
|
struct xfs_trans_res resv = {0};
|
||||||
|
|
||||||
|
return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record the indicated change to the given field for application
|
* Record the indicated change to the given field for application
|
||||||
* to the file system's superblock when the transaction commits.
|
* to the file system's superblock when the transaction commits.
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ typedef struct xfs_trans {
|
|||||||
int xfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
|
int xfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp,
|
||||||
uint blocks, uint rtextents, uint flags,
|
uint blocks, uint rtextents, uint flags,
|
||||||
struct xfs_trans **tpp);
|
struct xfs_trans **tpp);
|
||||||
|
int xfs_trans_alloc_empty(struct xfs_mount *mp,
|
||||||
|
struct xfs_trans **tpp);
|
||||||
void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
|
void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
|
||||||
|
|
||||||
struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp,
|
struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp,
|
||||||
|
|||||||
+10
-8
@@ -630,14 +630,16 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb)
|
|||||||
static inline netdev_features_t vlan_features_check(const struct sk_buff *skb,
|
static inline netdev_features_t vlan_features_check(const struct sk_buff *skb,
|
||||||
netdev_features_t features)
|
netdev_features_t features)
|
||||||
{
|
{
|
||||||
if (skb_vlan_tagged_multi(skb))
|
if (skb_vlan_tagged_multi(skb)) {
|
||||||
features = netdev_intersect_features(features,
|
/* In the case of multi-tagged packets, use a direct mask
|
||||||
NETIF_F_SG |
|
* instead of using netdev_interesect_features(), to make
|
||||||
NETIF_F_HIGHDMA |
|
* sure that only devices supporting NETIF_F_HW_CSUM will
|
||||||
NETIF_F_FRAGLIST |
|
* have checksum offloading support.
|
||||||
NETIF_F_HW_CSUM |
|
*/
|
||||||
NETIF_F_HW_VLAN_CTAG_TX |
|
features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
|
||||||
NETIF_F_HW_VLAN_STAG_TX);
|
NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
|
||||||
|
NETIF_F_HW_VLAN_STAG_TX;
|
||||||
|
}
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,12 +421,20 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
|
||||||
|
phys_addr_t end_addr);
|
||||||
#else
|
#else
|
||||||
static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
|
static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
|
||||||
|
phys_addr_t end_addr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_HAVE_MEMBLOCK */
|
#endif /* CONFIG_HAVE_MEMBLOCK */
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|||||||
@@ -640,7 +640,12 @@ enum {
|
|||||||
|
|
||||||
typedef void (*mlx5_cmd_cbk_t)(int status, void *context);
|
typedef void (*mlx5_cmd_cbk_t)(int status, void *context);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MLX5_CMD_ENT_STATE_PENDING_COMP,
|
||||||
|
};
|
||||||
|
|
||||||
struct mlx5_cmd_work_ent {
|
struct mlx5_cmd_work_ent {
|
||||||
|
unsigned long state;
|
||||||
struct mlx5_cmd_msg *in;
|
struct mlx5_cmd_msg *in;
|
||||||
struct mlx5_cmd_msg *out;
|
struct mlx5_cmd_msg *out;
|
||||||
void *uout;
|
void *uout;
|
||||||
@@ -838,7 +843,7 @@ void mlx5_eq_pagefault(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe);
|
|||||||
#endif
|
#endif
|
||||||
void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type);
|
void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type);
|
||||||
struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn);
|
struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn);
|
||||||
void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec);
|
void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced);
|
||||||
void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type);
|
void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type);
|
||||||
int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
|
int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
|
||||||
int nent, u64 mask, const char *name, struct mlx5_uar *uar);
|
int nent, u64 mask, const char *name, struct mlx5_uar *uar);
|
||||||
|
|||||||
@@ -672,6 +672,7 @@ typedef struct pglist_data {
|
|||||||
* is the first PFN that needs to be initialised.
|
* is the first PFN that needs to be initialised.
|
||||||
*/
|
*/
|
||||||
unsigned long first_deferred_pfn;
|
unsigned long first_deferred_pfn;
|
||||||
|
unsigned long static_init_size;
|
||||||
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
|
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
|
||||||
|
|
||||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||||
|
|||||||
+7
-1
@@ -107,10 +107,16 @@ struct dst_entry {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dst_metrics {
|
||||||
|
u32 metrics[RTAX_MAX];
|
||||||
|
atomic_t refcnt;
|
||||||
|
};
|
||||||
|
extern const struct dst_metrics dst_default_metrics;
|
||||||
|
|
||||||
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
|
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
|
||||||
extern const u32 dst_default_metrics[];
|
|
||||||
|
|
||||||
#define DST_METRICS_READ_ONLY 0x1UL
|
#define DST_METRICS_READ_ONLY 0x1UL
|
||||||
|
#define DST_METRICS_REFCOUNTED 0x2UL
|
||||||
#define DST_METRICS_FLAGS 0x3UL
|
#define DST_METRICS_FLAGS 0x3UL
|
||||||
#define __DST_METRICS_PTR(Y) \
|
#define __DST_METRICS_PTR(Y) \
|
||||||
((u32 *)((Y) & ~DST_METRICS_FLAGS))
|
((u32 *)((Y) & ~DST_METRICS_FLAGS))
|
||||||
|
|||||||
@@ -114,11 +114,11 @@ struct fib_info {
|
|||||||
__be32 fib_prefsrc;
|
__be32 fib_prefsrc;
|
||||||
u32 fib_tb_id;
|
u32 fib_tb_id;
|
||||||
u32 fib_priority;
|
u32 fib_priority;
|
||||||
u32 *fib_metrics;
|
struct dst_metrics *fib_metrics;
|
||||||
#define fib_mtu fib_metrics[RTAX_MTU-1]
|
#define fib_mtu fib_metrics->metrics[RTAX_MTU-1]
|
||||||
#define fib_window fib_metrics[RTAX_WINDOW-1]
|
#define fib_window fib_metrics->metrics[RTAX_WINDOW-1]
|
||||||
#define fib_rtt fib_metrics[RTAX_RTT-1]
|
#define fib_rtt fib_metrics->metrics[RTAX_RTT-1]
|
||||||
#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
|
#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1]
|
||||||
int fib_nhs;
|
int fib_nhs;
|
||||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||||
int fib_weight;
|
int fib_weight;
|
||||||
|
|||||||
@@ -1002,8 +1002,7 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (PageTransCompound(page)) {
|
if (PageTransCompound(page)) {
|
||||||
err = split_huge_page(page);
|
if (split_huge_page(page))
|
||||||
if (err)
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1696,6 +1696,29 @@ static void __init_memblock memblock_dump(struct memblock_type *type, char *name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned long __init_memblock
|
||||||
|
memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr)
|
||||||
|
{
|
||||||
|
struct memblock_region *rgn;
|
||||||
|
unsigned long size = 0;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for_each_memblock_type((&memblock.reserved), rgn) {
|
||||||
|
phys_addr_t start, end;
|
||||||
|
|
||||||
|
if (rgn->base + rgn->size < start_addr)
|
||||||
|
continue;
|
||||||
|
if (rgn->base > end_addr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
start = rgn->base;
|
||||||
|
end = start + rgn->size;
|
||||||
|
size += end - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void __init_memblock __memblock_dump_all(void)
|
void __init_memblock __memblock_dump_all(void)
|
||||||
{
|
{
|
||||||
pr_info("MEMBLOCK configuration:\n");
|
pr_info("MEMBLOCK configuration:\n");
|
||||||
|
|||||||
+2
-6
@@ -1587,12 +1587,8 @@ static int soft_offline_huge_page(struct page *page, int flags)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
|
pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
|
||||||
pfn, ret, page->flags);
|
pfn, ret, page->flags);
|
||||||
/*
|
if (!list_empty(&pagelist))
|
||||||
* We know that soft_offline_huge_page() tries to migrate
|
putback_movable_pages(&pagelist);
|
||||||
* only one hugepage pointed to by hpage, so we need not
|
|
||||||
* run through the pagelist here.
|
|
||||||
*/
|
|
||||||
putback_active_hugepage(hpage);
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-2
@@ -285,7 +285,7 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int nr = pagevec_count(pvec);
|
int nr = pagevec_count(pvec);
|
||||||
int delta_munlocked;
|
int delta_munlocked = -nr;
|
||||||
struct pagevec pvec_putback;
|
struct pagevec pvec_putback;
|
||||||
int pgrescued = 0;
|
int pgrescued = 0;
|
||||||
|
|
||||||
@@ -305,6 +305,8 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
|
|||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
__munlock_isolation_failed(page);
|
__munlock_isolation_failed(page);
|
||||||
|
} else {
|
||||||
|
delta_munlocked++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -316,7 +318,6 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
|
|||||||
pagevec_add(&pvec_putback, pvec->pages[i]);
|
pagevec_add(&pvec_putback, pvec->pages[i]);
|
||||||
pvec->pages[i] = NULL;
|
pvec->pages[i] = NULL;
|
||||||
}
|
}
|
||||||
delta_munlocked = -nr + pagevec_count(&pvec_putback);
|
|
||||||
__mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
|
__mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
|
||||||
spin_unlock_irq(zone_lru_lock(zone));
|
spin_unlock_irq(zone_lru_lock(zone));
|
||||||
|
|
||||||
|
|||||||
+22
-11
@@ -286,6 +286,26 @@ int page_group_by_mobility_disabled __read_mostly;
|
|||||||
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
|
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
|
||||||
static inline void reset_deferred_meminit(pg_data_t *pgdat)
|
static inline void reset_deferred_meminit(pg_data_t *pgdat)
|
||||||
{
|
{
|
||||||
|
unsigned long max_initialise;
|
||||||
|
unsigned long reserved_lowmem;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise at least 2G of a node but also take into account that
|
||||||
|
* two large system hashes that can take up 1GB for 0.25TB/node.
|
||||||
|
*/
|
||||||
|
max_initialise = max(2UL << (30 - PAGE_SHIFT),
|
||||||
|
(pgdat->node_spanned_pages >> 8));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate the all the memblock reservations (e.g. crash kernel)
|
||||||
|
* from the initial estimation to make sure we will initialize enough
|
||||||
|
* memory to boot.
|
||||||
|
*/
|
||||||
|
reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn,
|
||||||
|
pgdat->node_start_pfn + max_initialise);
|
||||||
|
max_initialise += reserved_lowmem;
|
||||||
|
|
||||||
|
pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages);
|
||||||
pgdat->first_deferred_pfn = ULONG_MAX;
|
pgdat->first_deferred_pfn = ULONG_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,20 +328,11 @@ static inline bool update_defer_init(pg_data_t *pgdat,
|
|||||||
unsigned long pfn, unsigned long zone_end,
|
unsigned long pfn, unsigned long zone_end,
|
||||||
unsigned long *nr_initialised)
|
unsigned long *nr_initialised)
|
||||||
{
|
{
|
||||||
unsigned long max_initialise;
|
|
||||||
|
|
||||||
/* Always populate low zones for address-contrained allocations */
|
/* Always populate low zones for address-contrained allocations */
|
||||||
if (zone_end < pgdat_end_pfn(pgdat))
|
if (zone_end < pgdat_end_pfn(pgdat))
|
||||||
return true;
|
return true;
|
||||||
/*
|
|
||||||
* Initialise at least 2G of a node but also take into account that
|
|
||||||
* two large system hashes that can take up 1GB for 0.25TB/node.
|
|
||||||
*/
|
|
||||||
max_initialise = max(2UL << (30 - PAGE_SHIFT),
|
|
||||||
(pgdat->node_spanned_pages >> 8));
|
|
||||||
|
|
||||||
(*nr_initialised)++;
|
(*nr_initialised)++;
|
||||||
if ((*nr_initialised > max_initialise) &&
|
if ((*nr_initialised > pgdat->static_init_size) &&
|
||||||
(pfn & (PAGES_PER_SECTION - 1)) == 0) {
|
(pfn & (PAGES_PER_SECTION - 1)) == 0) {
|
||||||
pgdat->first_deferred_pfn = pfn;
|
pgdat->first_deferred_pfn = pfn;
|
||||||
return false;
|
return false;
|
||||||
@@ -5911,7 +5922,6 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
|
|||||||
/* pg_data_t should be reset to zero when it's allocated */
|
/* pg_data_t should be reset to zero when it's allocated */
|
||||||
WARN_ON(pgdat->nr_zones || pgdat->kswapd_classzone_idx);
|
WARN_ON(pgdat->nr_zones || pgdat->kswapd_classzone_idx);
|
||||||
|
|
||||||
reset_deferred_meminit(pgdat);
|
|
||||||
pgdat->node_id = nid;
|
pgdat->node_id = nid;
|
||||||
pgdat->node_start_pfn = node_start_pfn;
|
pgdat->node_start_pfn = node_start_pfn;
|
||||||
pgdat->per_cpu_nodestats = NULL;
|
pgdat->per_cpu_nodestats = NULL;
|
||||||
@@ -5933,6 +5943,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
|
|||||||
(unsigned long)pgdat->node_mem_map);
|
(unsigned long)pgdat->node_mem_map);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
reset_deferred_meminit(pgdat);
|
||||||
free_area_init_core(pgdat);
|
free_area_init_core(pgdat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -496,10 +496,11 @@ static inline int check_valid_pointer(struct kmem_cache *s,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_section(char *text, u8 *addr, unsigned int length)
|
static void print_section(char *level, char *text, u8 *addr,
|
||||||
|
unsigned int length)
|
||||||
{
|
{
|
||||||
metadata_access_enable();
|
metadata_access_enable();
|
||||||
print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
|
print_hex_dump(level, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
|
||||||
length, 1);
|
length, 1);
|
||||||
metadata_access_disable();
|
metadata_access_disable();
|
||||||
}
|
}
|
||||||
@@ -636,14 +637,15 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
|
|||||||
p, p - addr, get_freepointer(s, p));
|
p, p - addr, get_freepointer(s, p));
|
||||||
|
|
||||||
if (s->flags & SLAB_RED_ZONE)
|
if (s->flags & SLAB_RED_ZONE)
|
||||||
print_section("Redzone ", p - s->red_left_pad, s->red_left_pad);
|
print_section(KERN_ERR, "Redzone ", p - s->red_left_pad,
|
||||||
|
s->red_left_pad);
|
||||||
else if (p > addr + 16)
|
else if (p > addr + 16)
|
||||||
print_section("Bytes b4 ", p - 16, 16);
|
print_section(KERN_ERR, "Bytes b4 ", p - 16, 16);
|
||||||
|
|
||||||
print_section("Object ", p, min_t(unsigned long, s->object_size,
|
print_section(KERN_ERR, "Object ", p,
|
||||||
PAGE_SIZE));
|
min_t(unsigned long, s->object_size, PAGE_SIZE));
|
||||||
if (s->flags & SLAB_RED_ZONE)
|
if (s->flags & SLAB_RED_ZONE)
|
||||||
print_section("Redzone ", p + s->object_size,
|
print_section(KERN_ERR, "Redzone ", p + s->object_size,
|
||||||
s->inuse - s->object_size);
|
s->inuse - s->object_size);
|
||||||
|
|
||||||
if (s->offset)
|
if (s->offset)
|
||||||
@@ -658,7 +660,8 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
|
|||||||
|
|
||||||
if (off != size_from_object(s))
|
if (off != size_from_object(s))
|
||||||
/* Beginning of the filler is the free pointer */
|
/* Beginning of the filler is the free pointer */
|
||||||
print_section("Padding ", p + off, size_from_object(s) - off);
|
print_section(KERN_ERR, "Padding ", p + off,
|
||||||
|
size_from_object(s) - off);
|
||||||
|
|
||||||
dump_stack();
|
dump_stack();
|
||||||
}
|
}
|
||||||
@@ -820,7 +823,7 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
|
|||||||
end--;
|
end--;
|
||||||
|
|
||||||
slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
|
slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
|
||||||
print_section("Padding ", end - remainder, remainder);
|
print_section(KERN_ERR, "Padding ", end - remainder, remainder);
|
||||||
|
|
||||||
restore_bytes(s, "slab padding", POISON_INUSE, end - remainder, end);
|
restore_bytes(s, "slab padding", POISON_INUSE, end - remainder, end);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -973,7 +976,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object,
|
|||||||
page->freelist);
|
page->freelist);
|
||||||
|
|
||||||
if (!alloc)
|
if (!alloc)
|
||||||
print_section("Object ", (void *)object,
|
print_section(KERN_INFO, "Object ", (void *)object,
|
||||||
s->object_size);
|
s->object_size);
|
||||||
|
|
||||||
dump_stack();
|
dump_stack();
|
||||||
@@ -5452,6 +5455,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
|
|||||||
char mbuf[64];
|
char mbuf[64];
|
||||||
char *buf;
|
char *buf;
|
||||||
struct slab_attribute *attr = to_slab_attr(slab_attrs[i]);
|
struct slab_attribute *attr = to_slab_attr(slab_attrs[i]);
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
if (!attr || !attr->store || !attr->show)
|
if (!attr || !attr->store || !attr->show)
|
||||||
continue;
|
continue;
|
||||||
@@ -5476,8 +5480,9 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
|
|||||||
buf = buffer;
|
buf = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->show(root_cache, buf);
|
len = attr->show(root_cache, buf);
|
||||||
attr->store(s, buf, strlen(buf));
|
if (len > 0)
|
||||||
|
attr->store(s, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer)
|
if (buffer)
|
||||||
|
|||||||
@@ -776,6 +776,13 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
|
|||||||
return -EPROTONOSUPPORT;
|
return -EPROTONOSUPPORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data[IFLA_BR_VLAN_DEFAULT_PVID]) {
|
||||||
|
__u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]);
|
||||||
|
|
||||||
|
if (defpvid >= VLAN_VID_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ static void br_stp_start(struct net_bridge *br)
|
|||||||
br_debug(br, "using kernel STP\n");
|
br_debug(br, "using kernel STP\n");
|
||||||
|
|
||||||
/* To start timers on any ports left in blocking */
|
/* To start timers on any ports left in blocking */
|
||||||
|
mod_timer(&br->hello_timer, jiffies + br->hello_time);
|
||||||
br_port_state_selection(br);
|
br_port_state_selection(br);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ static void br_hello_timer_expired(unsigned long arg)
|
|||||||
if (br->dev->flags & IFF_UP) {
|
if (br->dev->flags & IFF_UP) {
|
||||||
br_config_bpdu_generation(br);
|
br_config_bpdu_generation(br);
|
||||||
|
|
||||||
if (br->stp_enabled != BR_USER_STP)
|
if (br->stp_enabled == BR_KERNEL_STP)
|
||||||
mod_timer(&br->hello_timer,
|
mod_timer(&br->hello_timer,
|
||||||
round_jiffies(jiffies + br->hello_time));
|
round_jiffies(jiffies + br->hello_time));
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -151,13 +151,13 @@ int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dst_discard_out);
|
EXPORT_SYMBOL(dst_discard_out);
|
||||||
|
|
||||||
const u32 dst_default_metrics[RTAX_MAX + 1] = {
|
const struct dst_metrics dst_default_metrics = {
|
||||||
/* This initializer is needed to force linker to place this variable
|
/* This initializer is needed to force linker to place this variable
|
||||||
* into const section. Otherwise it might end into bss section.
|
* into const section. Otherwise it might end into bss section.
|
||||||
* We really want to avoid false sharing on this variable, and catch
|
* We really want to avoid false sharing on this variable, and catch
|
||||||
* any writes on it.
|
* any writes on it.
|
||||||
*/
|
*/
|
||||||
[RTAX_MAX] = 0xdeadbeef,
|
.refcnt = ATOMIC_INIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
void dst_init(struct dst_entry *dst, struct dst_ops *ops,
|
void dst_init(struct dst_entry *dst, struct dst_ops *ops,
|
||||||
@@ -169,7 +169,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
|
|||||||
if (dev)
|
if (dev)
|
||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
dst->ops = ops;
|
dst->ops = ops;
|
||||||
dst_init_metrics(dst, dst_default_metrics, true);
|
dst_init_metrics(dst, dst_default_metrics.metrics, true);
|
||||||
dst->expires = 0UL;
|
dst->expires = 0UL;
|
||||||
dst->path = dst;
|
dst->path = dst;
|
||||||
dst->from = NULL;
|
dst->from = NULL;
|
||||||
@@ -315,25 +315,30 @@ EXPORT_SYMBOL(dst_release);
|
|||||||
|
|
||||||
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
|
u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
|
||||||
{
|
{
|
||||||
u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
|
struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
u32 *old_p = __DST_METRICS_PTR(old);
|
struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old);
|
||||||
unsigned long prev, new;
|
unsigned long prev, new;
|
||||||
|
|
||||||
memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
|
atomic_set(&p->refcnt, 1);
|
||||||
|
memcpy(p->metrics, old_p->metrics, sizeof(p->metrics));
|
||||||
|
|
||||||
new = (unsigned long) p;
|
new = (unsigned long) p;
|
||||||
prev = cmpxchg(&dst->_metrics, old, new);
|
prev = cmpxchg(&dst->_metrics, old, new);
|
||||||
|
|
||||||
if (prev != old) {
|
if (prev != old) {
|
||||||
kfree(p);
|
kfree(p);
|
||||||
p = __DST_METRICS_PTR(prev);
|
p = (struct dst_metrics *)__DST_METRICS_PTR(prev);
|
||||||
if (prev & DST_METRICS_READ_ONLY)
|
if (prev & DST_METRICS_READ_ONLY)
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
} else if (prev & DST_METRICS_REFCOUNTED) {
|
||||||
|
if (atomic_dec_and_test(&old_p->refcnt))
|
||||||
|
kfree(old_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0);
|
||||||
|
return (u32 *)p;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dst_cow_metrics_generic);
|
EXPORT_SYMBOL(dst_cow_metrics_generic);
|
||||||
|
|
||||||
@@ -342,7 +347,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
|
|||||||
{
|
{
|
||||||
unsigned long prev, new;
|
unsigned long prev, new;
|
||||||
|
|
||||||
new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY;
|
new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY;
|
||||||
prev = cmpxchg(&dst->_metrics, old, new);
|
prev = cmpxchg(&dst->_metrics, old, new);
|
||||||
if (prev == old)
|
if (prev == old)
|
||||||
kfree(__DST_METRICS_PTR(old));
|
kfree(__DST_METRICS_PTR(old));
|
||||||
|
|||||||
@@ -2208,6 +2208,7 @@ bool bpf_helper_changes_skb_data(void *func)
|
|||||||
func == bpf_skb_change_proto ||
|
func == bpf_skb_change_proto ||
|
||||||
func == bpf_skb_change_tail ||
|
func == bpf_skb_change_tail ||
|
||||||
func == bpf_skb_pull_data ||
|
func == bpf_skb_pull_data ||
|
||||||
|
func == bpf_clone_redirect ||
|
||||||
func == bpf_l3_csum_replace ||
|
func == bpf_l3_csum_replace ||
|
||||||
func == bpf_l4_csum_replace)
|
func == bpf_l4_csum_replace)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user