Merge 6.1.112 into android14-6.1-lts

Changes in 6.1.112
	ASoC: SOF: mediatek: Add missing board compatible
	ASoC: allow module autoloading for table db1200_pids
	ASoC: allow module autoloading for table board_ids
	ALSA: hda/realtek - Fixed ALC256 headphone no sound
	ALSA: hda/realtek - FIxed ALC285 headphone no sound
	scsi: lpfc: Fix overflow build issue
	pinctrl: at91: make it work with current gpiolib
	hwmon: (asus-ec-sensors) remove VRM temp X570-E GAMING
	microblaze: don't treat zero reserved memory regions as error
	net: ftgmac100: Ensure tx descriptor updates are visible
	LoongArch: Define ARCH_IRQ_INIT_FLAGS as IRQ_NOPROBE
	wifi: iwlwifi: lower message level for FW buffer destination
	wifi: iwlwifi: mvm: fix iwl_mvm_scan_fits() calculation
	wifi: iwlwifi: mvm: pause TCM when the firmware is stopped
	wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead
	wifi: mac80211: free skb on error path in ieee80211_beacon_get_ap()
	wifi: iwlwifi: clear trans->state earlier upon error
	can: mcp251xfd: mcp251xfd_ring_init(): check TX-coalescing configuration
	ASoC: Intel: soc-acpi-cht: Make Lenovo Yoga Tab 3 X90F DMI match less strict
	ASoC: intel: fix module autoloading
	ASoC: tda7419: fix module autoloading
	spi: spidev: Add an entry for elgin,jg10309-01
	drm: komeda: Fix an issue related to normalized zpos
	spi: bcm63xx: Enable module autoloading
	smb: client: fix hang in wait_for_response() for negproto
	x86/hyperv: Set X86_FEATURE_TSC_KNOWN_FREQ when Hyper-V provides frequency
	tools: hv: rm .*.cmd when make clean
	block: Fix where bio IO priority gets set
	spi: spidev: Add missing spi_device_id for jg10309-01
	ocfs2: add bounds checking to ocfs2_xattr_find_entry()
	ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
	xfs: dquot shrinker doesn't check for XFS_DQFLAG_FREEING
	xfs: Fix deadlock on xfs_inodegc_worker
	xfs: fix extent busy updating
	xfs: don't use BMBT btree split workers for IO completion
	xfs: fix low space alloc deadlock
	xfs: prefer free inodes at ENOSPC over chunk allocation
	xfs: block reservation too large for minleft allocation
	xfs: fix uninitialized variable access
	xfs: quotacheck failure can race with background inode inactivation
	xfs: fix BUG_ON in xfs_getbmap()
	xfs: buffer pins need to hold a buffer reference
	xfs: defered work could create precommits
	xfs: fix AGF vs inode cluster buffer deadlock
	xfs: collect errors from inodegc for unlinked inode recovery
	xfs: fix ag count overflow during growfs
	xfs: remove WARN when dquot cache insertion fails
	xfs: fix the calculation for "end" and "length"
	xfs: load uncached unlinked inodes into memory on demand
	xfs: fix negative array access in xfs_getbmap
	xfs: fix unlink vs cluster buffer instantiation race
	xfs: correct calculation for agend and blockcount
	xfs: use i_prev_unlinked to distinguish inodes that are not on the unlinked list
	xfs: reload entire unlinked bucket lists
	xfs: make inode unlinked bucket recovery work with quotacheck
	xfs: fix reloading entire unlinked bucket lists
	xfs: set bnobt/cntbt numrecs correctly when formatting new AGs
	xfs: journal geometry is not properly bounds checked
	netfilter: nft_socket: make cgroupsv2 matching work with namespaces
	netfilter: nft_socket: Fix a NULL vs IS_ERR() bug in nft_socket_cgroup_subtree_level()
	netfilter: nft_set_pipapo: walk over current view on netlink dump
	netfilter: nf_tables: missing iterator type in lookup walk
	Revert "wifi: cfg80211: check wiphy mutex is held for wdev mutex"
	gpiolib: cdev: Ignore reconfiguration without direction
	gpio: prevent potential speculation leaks in gpio_device_get_desc()
	can: mcp251xfd: properly indent labels
	can: mcp251xfd: move mcp251xfd_timestamp_start()/stop() into mcp251xfd_chip_start/stop()
	selftests: mptcp: join: restrict fullmesh endp on 1st sf
	btrfs: calculate the right space for delayed refs when updating global reserve
	powercap: RAPL: fix invalid initialization for pl4_supported field
	x86/mm: Switch to new Intel CPU model defines
	USB: serial: pl2303: add device id for Macrosilicon MS3020
	USB: usbtmc: prevent kernel-usb-infoleak
	Linux 6.1.112

Change-Id: Iaa071658c42ce95ef06571de3232cfa7ddc96689
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-10-02 15:11:38 +00:00
89 changed files with 1254 additions and 461 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 111
SUBLEVEL = 112
EXTRAVERSION =
NAME = Curry Ramen

View File

@@ -9,6 +9,8 @@
extern atomic_t irq_err_count;
#define ARCH_IRQ_INIT_FLAGS IRQ_NOPROBE
/*
* interrupt-retrigger: NOP for now. This may not be appropriate for all
* machines, we'll see ...

View File

@@ -122,9 +122,6 @@ void __init init_IRQ(void)
panic("IPI IRQ request failed\n");
#endif
for (i = 0; i < NR_IRQS; i++)
irq_set_noprobe(i);
for_each_possible_cpu(i) {
page = alloc_pages_node(cpu_to_node(i), GFP_KERNEL, order);

View File

@@ -193,11 +193,6 @@ asmlinkage void __init mmu_init(void)
{
unsigned int kstart, ksize;
if (!memblock.reserved.cnt) {
pr_emerg("Error memory count\n");
machine_restart(NULL);
}
if ((u32) memblock.memory.regions[0].size < 0x400000) {
pr_emerg("Memory must be greater than 4MB\n");
machine_restart(NULL);

View File

@@ -324,6 +324,7 @@ static void __init ms_hyperv_init_platform(void)
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
x86_platform.calibrate_tsc = hv_get_tsc_khz;
x86_platform.calibrate_cpu = hv_get_tsc_khz;
setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
}
if (ms_hyperv.priv_high & HV_ISOLATION) {

View File

@@ -268,21 +268,17 @@ static void __init probe_page_size_mask(void)
}
}
#define INTEL_MATCH(_model) { .vendor = X86_VENDOR_INTEL, \
.family = 6, \
.model = _model, \
}
/*
* INVLPG may not properly flush Global entries
* on these CPUs when PCIDs are enabled.
*/
static const struct x86_cpu_id invlpg_miss_ids[] = {
INTEL_MATCH(INTEL_FAM6_ALDERLAKE ),
INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE ),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, 0),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, 0),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, 0),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, 0),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, 0),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, 0),
{}
};

View File

@@ -52,6 +52,7 @@
#include "blk-pm.h"
#include "blk-cgroup.h"
#include "blk-throttle.h"
#include "blk-ioprio.h"
struct dentry *blk_debugfs_root;
@@ -808,6 +809,14 @@ end_io:
}
EXPORT_SYMBOL(submit_bio_noacct);
static void bio_set_ioprio(struct bio *bio)
{
/* Nobody set ioprio so far? Initialize it based on task's nice value */
if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE)
bio->bi_ioprio = get_current_ioprio();
blkcg_set_ioprio(bio);
}
/**
* submit_bio - submit a bio to the block device layer for I/O
* @bio: The &struct bio which describes the I/O
@@ -833,6 +842,7 @@ void submit_bio(struct bio *bio)
count_vm_events(PGPGOUT, bio_sectors(bio));
}
bio_set_ioprio(bio);
submit_bio_noacct(bio);
}
EXPORT_SYMBOL(submit_bio);

View File

@@ -42,7 +42,6 @@
#include "blk-stat.h"
#include "blk-mq-sched.h"
#include "blk-rq-qos.h"
#include "blk-ioprio.h"
static DEFINE_PER_CPU(struct llist_head, blk_cpu_done);
@@ -2948,14 +2947,6 @@ static bool blk_mq_can_use_cached_rq(struct request *rq, struct blk_plug *plug,
return true;
}
static void bio_set_ioprio(struct bio *bio)
{
/* Nobody set ioprio so far? Initialize it based on task's nice value */
if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE)
bio->bi_ioprio = get_current_ioprio();
blkcg_set_ioprio(bio);
}
/**
* blk_mq_submit_bio - Create and send a request to block device.
* @bio: Bio pointer.
@@ -2979,7 +2970,6 @@ void blk_mq_submit_bio(struct bio *bio)
blk_status_t ret;
bio = blk_queue_bounce(bio, q);
bio_set_ioprio(bio);
if (plug) {
rq = rq_list_peek(&plug->cached_rq);

View File

@@ -1523,12 +1523,14 @@ static long linereq_set_config_unlocked(struct linereq *lr,
line = &lr->lines[i];
desc = lr->lines[i].desc;
flags = gpio_v2_line_config_flags(lc, i);
/*
* Lines not explicitly reconfigured as input or output
* are left unchanged.
*/
if (!(flags & GPIO_V2_LINE_DIRECTION_FLAGS))
continue;
gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS;
/*
* Lines have to be requested explicitly for input
* or output, else the line will be treated "as is".
*/
if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
int val = gpio_v2_line_config_output_value(lc, i);
@@ -1536,7 +1538,7 @@ static long linereq_set_config_unlocked(struct linereq *lr,
ret = gpiod_direction_output(desc, val);
if (ret)
return ret;
} else if (flags & GPIO_V2_LINE_FLAG_INPUT) {
} else {
ret = gpiod_direction_input(desc);
if (ret)
return ret;

View File

@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/nospec.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/device.h>
@@ -146,7 +147,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *gc,
if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL);
return &gdev->descs[hwnum];
return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
}
EXPORT_SYMBOL_GPL(gpiochip_get_desc);

View File

@@ -163,6 +163,7 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
struct drm_plane *plane;
struct list_head zorder_list;
int order = 0, err;
u32 slave_zpos = 0;
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
crtc->base.id, crtc->name);
@@ -202,10 +203,13 @@ static int komeda_crtc_normalize_zpos(struct drm_crtc *crtc,
plane_st->zpos, plane_st->normalized_zpos);
/* calculate max slave zorder */
if (has_bit(drm_plane_index(plane), kcrtc->slave_planes))
if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) {
slave_zpos = plane_st->normalized_zpos;
if (to_kplane_st(plane_st)->layer_split)
slave_zpos++;
kcrtc_st->max_slave_zorder =
max(plane_st->normalized_zpos,
kcrtc_st->max_slave_zorder);
max(slave_zpos, kcrtc_st->max_slave_zorder);
}
}
crtc_st->zpos_changed = true;

View File

@@ -369,7 +369,7 @@ static const struct ec_board_info board_info_strix_b550_i_gaming = {
static const struct ec_board_info board_info_strix_x570_e_gaming = {
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
SENSOR_TEMP_T_SENSOR |
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
SENSOR_IN_CPU_CORE,
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,

View File

@@ -744,6 +744,7 @@ static void mcp251xfd_chip_stop(struct mcp251xfd_priv *priv,
mcp251xfd_chip_interrupts_disable(priv);
mcp251xfd_chip_rx_int_disable(priv);
mcp251xfd_timestamp_stop(priv);
mcp251xfd_chip_sleep(priv);
}
@@ -763,6 +764,8 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
if (err)
goto out_chip_stop;
mcp251xfd_timestamp_start(priv);
err = mcp251xfd_set_bittiming(priv);
if (err)
goto out_chip_stop;
@@ -791,7 +794,7 @@ static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
return 0;
out_chip_stop:
out_chip_stop:
mcp251xfd_dump(priv);
mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
@@ -1576,7 +1579,7 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
handled = IRQ_HANDLED;
} while (1);
out_fail:
out_fail:
can_rx_offload_threaded_irq_finish(&priv->offload);
netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
@@ -1610,11 +1613,12 @@ static int mcp251xfd_open(struct net_device *ndev)
if (err)
goto out_mcp251xfd_ring_free;
mcp251xfd_timestamp_init(priv);
err = mcp251xfd_chip_start(priv);
if (err)
goto out_transceiver_disable;
mcp251xfd_timestamp_init(priv);
clear_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
can_rx_offload_enable(&priv->offload);
@@ -1641,22 +1645,21 @@ static int mcp251xfd_open(struct net_device *ndev)
return 0;
out_free_irq:
out_free_irq:
free_irq(spi->irq, priv);
out_destroy_workqueue:
out_destroy_workqueue:
destroy_workqueue(priv->wq);
out_can_rx_offload_disable:
out_can_rx_offload_disable:
can_rx_offload_disable(&priv->offload);
set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
mcp251xfd_timestamp_stop(priv);
out_transceiver_disable:
out_transceiver_disable:
mcp251xfd_transceiver_disable(priv);
out_mcp251xfd_ring_free:
out_mcp251xfd_ring_free:
mcp251xfd_ring_free(priv);
out_pm_runtime_put:
out_pm_runtime_put:
mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
pm_runtime_put(ndev->dev.parent);
out_close_candev:
out_close_candev:
close_candev(ndev);
return err;
@@ -1674,7 +1677,6 @@ static int mcp251xfd_stop(struct net_device *ndev)
free_irq(ndev->irq, priv);
destroy_workqueue(priv->wq);
can_rx_offload_disable(&priv->offload);
mcp251xfd_timestamp_stop(priv);
mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
mcp251xfd_transceiver_disable(priv);
mcp251xfd_ring_free(priv);
@@ -1820,9 +1822,9 @@ mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id,
*effective_speed_hz_slow = xfer[0].effective_speed_hz;
*effective_speed_hz_fast = xfer[1].effective_speed_hz;
out_kfree_buf_tx:
out_kfree_buf_tx:
kfree(buf_tx);
out_kfree_buf_rx:
out_kfree_buf_rx:
kfree(buf_rx);
return err;
@@ -1936,13 +1938,13 @@ static int mcp251xfd_register(struct mcp251xfd_priv *priv)
return 0;
out_unregister_candev:
out_unregister_candev:
unregister_candev(ndev);
out_chip_sleep:
out_chip_sleep:
mcp251xfd_chip_sleep(priv);
out_runtime_disable:
out_runtime_disable:
pm_runtime_disable(ndev->dev.parent);
out_runtime_put_noidle:
out_runtime_put_noidle:
pm_runtime_put_noidle(ndev->dev.parent);
mcp251xfd_clks_and_vdd_disable(priv);
@@ -2162,9 +2164,9 @@ static int mcp251xfd_probe(struct spi_device *spi)
return 0;
out_can_rx_offload_del:
out_can_rx_offload_del:
can_rx_offload_del(&priv->offload);
out_free_candev:
out_free_candev:
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
free_candev(ndev);

View File

@@ -94,7 +94,7 @@ static void mcp251xfd_dump_registers(const struct mcp251xfd_priv *priv,
kfree(buf);
}
out:
out:
mcp251xfd_dump_header(iter, MCP251XFD_DUMP_OBJECT_TYPE_REG, reg);
}

View File

@@ -397,7 +397,7 @@ mcp251xfd_regmap_crc_read(void *context,
return err;
}
out:
out:
memcpy(val_buf, buf_rx->data, val_len);
return 0;

View File

@@ -280,7 +280,7 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
const struct mcp251xfd_rx_ring *rx_ring;
u16 base = 0, ram_used;
u8 fifo_nr = 1;
int i;
int err = 0, i;
netdev_reset_queue(priv->ndev);
@@ -376,10 +376,18 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
netdev_err(priv->ndev,
"Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
ram_used, MCP251XFD_RAM_SIZE);
return -ENOMEM;
err = -ENOMEM;
}
return 0;
if (priv->tx_obj_num_coalesce_irq &&
priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
netdev_err(priv->ndev,
"Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
err = -EINVAL;
}
return err;
}
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)

View File

@@ -219,7 +219,7 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
total_frame_len += frame_len;
}
out_netif_wake_queue:
out_netif_wake_queue:
len = i; /* number of handled goods TEFs */
if (len) {
struct mcp251xfd_tef_ring *ring = priv->tef;

View File

@@ -48,9 +48,12 @@ void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv)
cc->shift = 1;
cc->mult = clocksource_hz2mult(priv->can.clock.freq, cc->shift);
timecounter_init(&priv->tc, &priv->cc, ktime_get_real_ns());
INIT_DELAYED_WORK(&priv->timestamp, mcp251xfd_timestamp_work);
}
void mcp251xfd_timestamp_start(struct mcp251xfd_priv *priv)
{
timecounter_init(&priv->tc, &priv->cc, ktime_get_real_ns());
schedule_delayed_work(&priv->timestamp,
MCP251XFD_TIMESTAMP_WORK_DELAY_SEC * HZ);
}

View File

@@ -939,6 +939,7 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv);
int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv);
int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv);
void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv);
void mcp251xfd_timestamp_start(struct mcp251xfd_priv *priv);
void mcp251xfd_timestamp_stop(struct mcp251xfd_priv *priv);
void mcp251xfd_tx_obj_write_sync(struct work_struct *work);

View File

@@ -566,7 +566,7 @@ static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
(*processed)++;
return true;
drop:
drop:
/* Clean rxdes0 (which resets own bit) */
rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask);
priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer);
@@ -650,6 +650,11 @@ static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
ftgmac100_free_tx_packet(priv, pointer, skb, txdes, ctl_stat);
txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask);
/* Ensure the descriptor config is visible before setting the tx
* pointer.
*/
smp_wmb();
priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer);
return true;
@@ -803,6 +808,11 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
dma_wmb();
first->txdes0 = cpu_to_le32(f_ctl_stat);
/* Ensure the descriptor config is visible before setting the tx
* pointer.
*/
smp_wmb();
/* Update next TX pointer */
priv->tx_pointer = pointer;
@@ -823,7 +833,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
dma_err:
dma_err:
if (net_ratelimit())
netdev_err(netdev, "map tx fragment failed\n");
@@ -845,7 +855,7 @@ static netdev_tx_t ftgmac100_hard_start_xmit(struct sk_buff *skb,
* last fragment, so we know ftgmac100_free_tx_packet()
* hasn't freed the skb yet.
*/
drop:
drop:
/* Drop the packet */
dev_kfree_skb_any(skb);
netdev->stats.tx_dropped++;
@@ -1338,7 +1348,7 @@ static void ftgmac100_reset(struct ftgmac100 *priv)
ftgmac100_init_all(priv, true);
netdev_dbg(netdev, "Reset done !\n");
bail:
bail:
if (priv->mii_bus)
mutex_unlock(&priv->mii_bus->mdio_lock);
if (netdev->phydev)
@@ -1537,15 +1547,15 @@ static int ftgmac100_open(struct net_device *netdev)
return 0;
err_ncsi:
err_ncsi:
napi_disable(&priv->napi);
netif_stop_queue(netdev);
err_alloc:
err_alloc:
ftgmac100_free_buffers(priv);
free_irq(netdev->irq, netdev);
err_irq:
err_irq:
netif_napi_del(&priv->napi);
err_hw:
err_hw:
iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
ftgmac100_free_rings(priv);
return err;

View File

@@ -3131,7 +3131,7 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
{
int ret __maybe_unused = 0;
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
if (!iwl_trans_fw_running(fwrt->trans))
return;
if (fw_has_capa(&fwrt->fw->ucode_capa,

View File

@@ -1472,8 +1472,8 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans, bool sync)
/* prevent double restarts due to the same erroneous FW */
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) {
iwl_op_mode_nic_error(trans->op_mode, sync);
trans->state = IWL_TRANS_NO_FW;
iwl_op_mode_nic_error(trans->op_mode, sync);
}
}

View File

@@ -4800,6 +4800,10 @@ static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
int i;
if (!iwl_mvm_has_new_tx_api(mvm)) {
/* we can't ask the firmware anything if it is dead */
if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status))
return;
if (drop) {
mutex_lock(&mvm->mutex);
iwl_mvm_flush_tx_path(mvm,
@@ -4881,8 +4885,11 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
/* this can take a while, and we may need/want other operations
* to succeed while doing this, so do it without the mutex held
* If the firmware is dead, this can't work...
*/
if (!drop && !iwl_mvm_has_new_tx_api(mvm))
if (!drop && !iwl_mvm_has_new_tx_api(mvm) &&
!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
&mvm->status))
iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
}

View File

@@ -1366,6 +1366,8 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_mvm_pause_tcm(mvm, false);
iwl_fw_dbg_stop_sync(&mvm->fwrt);
iwl_trans_stop_device(mvm->trans);
iwl_free_fw_paging(&mvm->fwrt);

View File

@@ -824,8 +824,8 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
return ((n_ssids <= PROBE_OPTION_MAX) &&
(n_channels <= mvm->fw->ucode_capa.n_scan_channels) &
(ies->common_ie_len +
ies->len[NL80211_BAND_2GHZ] +
ies->len[NL80211_BAND_5GHZ] <=
ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] +
ies->len[NL80211_BAND_6GHZ] <=
iwl_mvm_max_scan_ie_fw_cmd_room(mvm)));
}
@@ -2935,18 +2935,16 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
params.n_channels = j;
}
if (non_psc_included &&
!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, params.n_channels)) {
kfree(params.channels);
return -ENOBUFS;
if (!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, params.n_channels)) {
ret = -ENOBUFS;
goto out;
}
uid = iwl_mvm_build_scan_cmd(mvm, vif, &hcmd, &params, type);
if (non_psc_included)
kfree(params.channels);
if (uid < 0)
return uid;
if (uid < 0) {
ret = uid;
goto out;
}
ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (!ret) {
@@ -2963,6 +2961,9 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
}
out:
if (non_psc_included)
kfree(params.channels);
return ret;
}

View File

@@ -68,7 +68,8 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,
}
break;
default:
IWL_ERR(trans, "WRT: Invalid buffer destination\n");
IWL_DEBUG_FW(trans, "WRT: Invalid buffer destination (%d)\n",
le32_to_cpu(fw_mon_cfg->buf_location));
}
out:
if (dbg_flags)

View File

@@ -1420,8 +1420,11 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
/* We will handle a range of GPIO pins */
for (i = 0; i < gpio_banks; i++)
if (gpio_chips[i])
if (gpio_chips[i]) {
pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
gpiochip_add_pin_range(&gpio_chips[i]->chip, dev_name(info->pctl->dev), 0,
gpio_chips[i]->range.pin_base, gpio_chips[i]->range.npins);
}
dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");

View File

@@ -136,12 +136,12 @@ static int rapl_msr_write_raw(int cpu, struct reg_action *ra)
/* List of verified CPUs. */
static const struct x86_cpu_id pl4_support_ids[] = {
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE, X86_FEATURE_ANY },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_L, X86_FEATURE_ANY },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ALDERLAKE_N, X86_FEATURE_ANY },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE, X86_FEATURE_ANY },
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_RAPTORLAKE_P, X86_FEATURE_ANY },
X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL),
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL),
X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL),
{}
};

View File

@@ -5409,7 +5409,7 @@ lpfc_get_cgnbuf_info(struct bsg_job *job)
struct get_cgnbuf_info_req *cgnbuf_req;
struct lpfc_cgn_info *cp;
uint8_t *cgn_buff;
int size, cinfosz;
size_t size, cinfosz;
int rc = 0;
if (job->request_len < sizeof(struct fc_bsg_request) +

View File

@@ -482,6 +482,7 @@ static const struct of_device_id bcm63xx_spi_of_match[] = {
{ .compatible = "brcm,bcm6358-spi", .data = &bcm6358_spi_reg_offsets },
{ },
};
MODULE_DEVICE_TABLE(of, bcm63xx_spi_of_match);
static int bcm63xx_spi_probe(struct platform_device *pdev)
{

View File

@@ -694,6 +694,7 @@ static struct class *spidev_class;
static const struct spi_device_id spidev_spi_ids[] = {
{ .name = "bh2228fv" },
{ .name = "dh2228fv" },
{ .name = "jg10309-01" },
{ .name = "ltc2488" },
{ .name = "sx1301" },
{ .name = "bk4" },
@@ -722,6 +723,7 @@ static int spidev_of_check(struct device *dev)
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "cisco,spi-petra", .data = &spidev_of_check },
{ .compatible = "dh,dhcom-board", .data = &spidev_of_check },
{ .compatible = "elgin,jg10309-01", .data = &spidev_of_check },
{ .compatible = "lineartechnology,ltc2488", .data = &spidev_of_check },
{ .compatible = "lwn,bk4", .data = &spidev_of_check },
{ .compatible = "menlo,m53cpld", .data = &spidev_of_check },

View File

@@ -754,7 +754,7 @@ static struct urb *usbtmc_create_urb(void)
if (!urb)
return NULL;
dmabuf = kmalloc(bufsize, GFP_KERNEL);
dmabuf = kzalloc(bufsize, GFP_KERNEL);
if (!dmabuf) {
usb_free_urb(urb);
return NULL;

View File

@@ -118,6 +118,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
{ USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_PRODUCT_ID) },
{ USB_DEVICE(MACROSILICON_VENDOR_ID, MACROSILICON_MS3020_PRODUCT_ID) },
{ } /* Terminating entry */
};

View File

@@ -171,3 +171,7 @@
/* Allied Telesis VT-Kit3 */
#define AT_VENDOR_ID 0x0caa
#define AT_VTKIT3_PRODUCT_ID 0x3001
/* Macrosilicon MS3020 */
#define MACROSILICON_VENDOR_ID 0x345f
#define MACROSILICON_MS3020_PRODUCT_ID 0x3020

View File

@@ -384,17 +384,19 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
/*
* But we also want to reserve enough space so we can do the fallback
* global reserve for an unlink, which is an additional 5 items (see the
* comment in __unlink_start_trans for what we're modifying.)
* global reserve for an unlink, which is an additional
* BTRFS_UNLINK_METADATA_UNITS items.
*
* But we also need space for the delayed ref updates from the unlink,
* so its 10, 5 for the actual operation, and 5 for the delayed ref
* updates.
* so add BTRFS_UNLINK_METADATA_UNITS units for delayed refs, one for
* each unlink metadata item.
*/
min_items += 10;
min_items += BTRFS_UNLINK_METADATA_UNITS;
num_bytes = max_t(u64, num_bytes,
btrfs_calc_insert_metadata_size(fs_info, min_items));
btrfs_calc_insert_metadata_size(fs_info, min_items) +
btrfs_calc_delayed_ref_bytes(fs_info,
BTRFS_UNLINK_METADATA_UNITS));
spin_lock(&sinfo->lock);
spin_lock(&block_rsv->lock);

View File

@@ -50,6 +50,18 @@ struct btrfs_block_rsv {
u64 qgroup_rsv_reserved;
};
/*
* Number of metadata items necessary for an unlink operation:
*
* 1 for the possible orphan item
* 1 for the dir item
* 1 for the dir index
* 1 for the inode ref
* 1 for the inode
* 1 for the parent inode
*/
#define BTRFS_UNLINK_METADATA_UNITS 6
void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, enum btrfs_rsv_type type);
void btrfs_init_root_block_rsv(struct btrfs_root *root);
struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info,

View File

@@ -253,6 +253,27 @@ extern struct kmem_cache *btrfs_delayed_extent_op_cachep;
int __init btrfs_delayed_ref_init(void);
void __cold btrfs_delayed_ref_exit(void);
static inline u64 btrfs_calc_delayed_ref_bytes(struct btrfs_fs_info *fs_info,
int num_delayed_refs)
{
u64 num_bytes;
num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_delayed_refs);
/*
* We have to check the mount option here because we could be enabling
* the free space tree for the first time and don't have the compat_ro
* option set yet.
*
* We need extra reservations if we have the free space tree because
* we'll have to modify that tree as well.
*/
if (btrfs_test_opt(fs_info, FREE_SPACE_TREE))
num_bytes *= 2;
return num_bytes;
}
static inline void btrfs_init_generic_ref(struct btrfs_ref *generic_ref,
int action, u64 bytenr, u64 len, u64 parent)
{

View File

@@ -1066,13 +1066,13 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
return i_ret + b_ret;
}
static int ocfs2_xattr_find_entry(int name_index,
static int ocfs2_xattr_find_entry(struct inode *inode, int name_index,
const char *name,
struct ocfs2_xattr_search *xs)
{
struct ocfs2_xattr_entry *entry;
size_t name_len;
int i, cmp = 1;
int i, name_offset, cmp = 1;
if (name == NULL)
return -EINVAL;
@@ -1080,13 +1080,22 @@ static int ocfs2_xattr_find_entry(int name_index,
name_len = strlen(name);
entry = xs->here;
for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) {
if ((void *)entry >= xs->end) {
ocfs2_error(inode->i_sb, "corrupted xattr entries");
return -EFSCORRUPTED;
}
cmp = name_index - ocfs2_xattr_get_type(entry);
if (!cmp)
cmp = name_len - entry->xe_name_len;
if (!cmp)
cmp = memcmp(name, (xs->base +
le16_to_cpu(entry->xe_name_offset)),
name_len);
if (!cmp) {
name_offset = le16_to_cpu(entry->xe_name_offset);
if ((xs->base + name_offset + name_len) > xs->end) {
ocfs2_error(inode->i_sb,
"corrupted xattr entries");
return -EFSCORRUPTED;
}
cmp = memcmp(name, (xs->base + name_offset), name_len);
}
if (cmp == 0)
break;
entry += 1;
@@ -1170,7 +1179,7 @@ static int ocfs2_xattr_ibody_get(struct inode *inode,
xs->base = (void *)xs->header;
xs->here = xs->header->xh_entries;
ret = ocfs2_xattr_find_entry(name_index, name, xs);
ret = ocfs2_xattr_find_entry(inode, name_index, name, xs);
if (ret)
return ret;
size = le64_to_cpu(xs->here->xe_value_size);
@@ -2702,7 +2711,7 @@ static int ocfs2_xattr_ibody_find(struct inode *inode,
/* Find the named attribute. */
if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
ret = ocfs2_xattr_find_entry(name_index, name, xs);
ret = ocfs2_xattr_find_entry(inode, name_index, name, xs);
if (ret && ret != -ENODATA)
return ret;
xs->not_found = ret;
@@ -2837,7 +2846,7 @@ static int ocfs2_xattr_block_find(struct inode *inode,
xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size;
xs->here = xs->header->xh_entries;
ret = ocfs2_xattr_find_entry(name_index, name, xs);
ret = ocfs2_xattr_find_entry(inode, name_index, name, xs);
} else
ret = ocfs2_xattr_index_block_find(inode, blk_bh,
name_index,

View File

@@ -673,6 +673,19 @@ allocate_buffers(struct TCP_Server_Info *server)
static bool
server_unresponsive(struct TCP_Server_Info *server)
{
/*
* If we're in the process of mounting a share or reconnecting a session
* and the server abruptly shut down (e.g. socket wasn't closed, packet
* had been ACK'ed but no SMB response), don't wait longer than 20s to
* negotiate protocol.
*/
spin_lock(&server->srv_lock);
if (server->tcpStatus == CifsInNegotiate &&
time_after(jiffies, server->lstrp + 20 * HZ)) {
spin_unlock(&server->srv_lock);
cifs_reconnect(server, false);
return true;
}
/*
* We need to wait 3 echo intervals to make sure we handle such
* situations right:
@@ -684,7 +697,6 @@ server_unresponsive(struct TCP_Server_Info *server)
* 65s kernel_recvmsg times out, and we see that we haven't gotten
* a response in >60s.
*/
spin_lock(&server->srv_lock);
if ((server->tcpStatus == CifsGood ||
server->tcpStatus == CifsNeedNegotiate) &&
(!server->ops->can_echo || server->ops->can_echo(server)) &&

View File

@@ -415,10 +415,12 @@ xfs_freesp_init_recs(
ASSERT(start >= mp->m_ag_prealloc_blocks);
if (start != mp->m_ag_prealloc_blocks) {
/*
* Modify first record to pad stripe align of log
* Modify first record to pad stripe align of log and
* bump the record count.
*/
arec->ar_blockcount = cpu_to_be32(start -
mp->m_ag_prealloc_blocks);
be16_add_cpu(&block->bb_numrecs, 1);
nrec = arec + 1;
/*
@@ -429,7 +431,6 @@ xfs_freesp_init_recs(
be32_to_cpu(arec->ar_startblock) +
be32_to_cpu(arec->ar_blockcount));
arec = nrec;
be16_add_cpu(&block->bb_numrecs, 1);
}
/*
* Change record start to after the internal log
@@ -438,15 +439,13 @@ xfs_freesp_init_recs(
}
/*
* Calculate the record block count and check for the case where
* the log might have consumed all available space in the AG. If
* so, reset the record count to 0 to avoid exposure of an invalid
* record start block.
* Calculate the block count of this record; if it is nonzero,
* increment the record count.
*/
arec->ar_blockcount = cpu_to_be32(id->agsize -
be32_to_cpu(arec->ar_startblock));
if (!arec->ar_blockcount)
block->bb_numrecs = 0;
if (arec->ar_blockcount)
be16_add_cpu(&block->bb_numrecs, 1);
}
/*
@@ -458,7 +457,7 @@ xfs_bnoroot_init(
struct xfs_buf *bp,
struct aghdr_init_data *id)
{
xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno);
xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 0, id->agno);
xfs_freesp_init_recs(mp, bp, id);
}
@@ -468,7 +467,7 @@ xfs_cntroot_init(
struct xfs_buf *bp,
struct aghdr_init_data *id)
{
xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno);
xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 0, id->agno);
xfs_freesp_init_recs(mp, bp, id);
}

View File

@@ -3164,10 +3164,13 @@ xfs_alloc_vextent(
xfs_alloctype_t type; /* input allocation type */
int bump_rotor = 0;
xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */
xfs_agnumber_t minimum_agno = 0;
mp = args->mp;
type = args->otype = args->type;
args->agbno = NULLAGBLOCK;
if (args->tp->t_firstblock != NULLFSBLOCK)
minimum_agno = XFS_FSB_TO_AGNO(mp, args->tp->t_firstblock);
/*
* Just fix this up, for the case where the last a.g. is shorter
* (or there's only one a.g.) and the caller couldn't easily figure
@@ -3201,6 +3204,13 @@ xfs_alloc_vextent(
*/
args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
args->pag = xfs_perag_get(mp, args->agno);
if (minimum_agno > args->agno) {
trace_xfs_alloc_vextent_skip_deadlock(args);
error = 0;
break;
}
error = xfs_alloc_fix_freelist(args, 0);
if (error) {
trace_xfs_alloc_vextent_nofix(args);
@@ -3232,6 +3242,8 @@ xfs_alloc_vextent(
case XFS_ALLOCTYPE_FIRST_AG:
/*
* Rotate through the allocation groups looking for a winner.
* If we are blocking, we must obey minimum_agno contraints for
* avoiding ABBA deadlocks on AGF locking.
*/
if (type == XFS_ALLOCTYPE_FIRST_AG) {
/*
@@ -3239,7 +3251,7 @@ xfs_alloc_vextent(
*/
args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
args->type = XFS_ALLOCTYPE_THIS_AG;
sagno = 0;
sagno = minimum_agno;
flags = 0;
} else {
/*
@@ -3248,6 +3260,7 @@ xfs_alloc_vextent(
args->agno = sagno = XFS_FSB_TO_AGNO(mp, args->fsbno);
flags = XFS_ALLOC_FLAG_TRYLOCK;
}
/*
* Loop over allocation groups twice; first time with
* trylock set, second time without.
@@ -3276,19 +3289,21 @@ xfs_alloc_vextent(
if (args->agno == sagno &&
type == XFS_ALLOCTYPE_START_BNO)
args->type = XFS_ALLOCTYPE_THIS_AG;
/*
* For the first allocation, we can try any AG to get
* space. However, if we already have allocated a
* block, we don't want to try AGs whose number is below
* sagno. Otherwise, we may end up with out-of-order
* locking of AGF, which might cause deadlock.
*/
* If we are try-locking, we can't deadlock on AGF
* locks, so we can wrap all the way back to the first
* AG. Otherwise, wrap back to the start AG so we can't
* deadlock, and let the end of scan handler decide what
* to do next.
*/
if (++(args->agno) == mp->m_sb.sb_agcount) {
if (args->tp->t_firstblock != NULLFSBLOCK)
args->agno = sagno;
else
if (flags & XFS_ALLOC_FLAG_TRYLOCK)
args->agno = 0;
else
args->agno = sagno;
}
/*
* Reached the starting a.g., must either be done
* or switch to non-trylock mode.
@@ -3300,7 +3315,14 @@ xfs_alloc_vextent(
break;
}
/*
* Blocking pass next, so we must obey minimum
* agno constraints to avoid ABBA AGF deadlocks.
*/
flags = 0;
if (minimum_agno > sagno)
sagno = minimum_agno;
if (type == XFS_ALLOCTYPE_START_BNO) {
args->agbno = XFS_FSB_TO_AGBNO(mp,
args->fsbno);
@@ -3322,9 +3344,9 @@ xfs_alloc_vextent(
ASSERT(0);
/* NOTREACHED */
}
if (args->agbno == NULLAGBLOCK)
if (args->agbno == NULLAGBLOCK) {
args->fsbno = NULLFSBLOCK;
else {
} else {
args->fsbno = XFS_AGB_TO_FSB(mp, args->agno, args->agbno);
#ifdef DEBUG
ASSERT(args->len >= args->minlen);
@@ -3335,6 +3357,29 @@ xfs_alloc_vextent(
#endif
}
/*
* We end up here with a locked AGF. If we failed, the caller is likely
* going to try to allocate again with different parameters, and that
* can widen the AGs that are searched for free space. If we have to do
* BMBT block allocation, we have to do a new allocation.
*
* Hence leaving this function with the AGF locked opens up potential
* ABBA AGF deadlocks because a future allocation attempt in this
* transaction may attempt to lock a lower number AGF.
*
* We can't release the AGF until the transaction is commited, so at
* this point we must update the "firstblock" tracker to point at this
* AG if the tracker is empty or points to a lower AG. This allows the
* next allocation attempt to be modified appropriately to avoid
* deadlocks.
*/
if (args->agbp &&
(args->tp->t_firstblock == NULLFSBLOCK ||
args->pag->pag_agno > minimum_agno)) {
args->tp->t_firstblock = XFS_AGB_TO_FSB(mp,
args->pag->pag_agno, 0);
}
xfs_perag_put(args->pag);
return 0;
error0:

View File

@@ -3413,21 +3413,7 @@ xfs_bmap_process_allocated_extent(
xfs_fileoff_t orig_offset,
xfs_extlen_t orig_length)
{
int nullfb;
nullfb = ap->tp->t_firstblock == NULLFSBLOCK;
/*
* check the allocation happened at the same or higher AG than
* the first block that was allocated.
*/
ASSERT(nullfb ||
XFS_FSB_TO_AGNO(args->mp, ap->tp->t_firstblock) <=
XFS_FSB_TO_AGNO(args->mp, args->fsbno));
ap->blkno = args->fsbno;
if (nullfb)
ap->tp->t_firstblock = args->fsbno;
ap->length = args->len;
/*
* If the extent size hint is active, we tried to round the
@@ -4256,7 +4242,7 @@ xfs_bmapi_convert_unwritten(
return 0;
}
static inline xfs_extlen_t
xfs_extlen_t
xfs_bmapi_minleft(
struct xfs_trans *tp,
struct xfs_inode *ip,

View File

@@ -220,6 +220,8 @@ int xfs_bmap_add_extent_unwritten_real(struct xfs_trans *tp,
struct xfs_inode *ip, int whichfork,
struct xfs_iext_cursor *icur, struct xfs_btree_cur **curp,
struct xfs_bmbt_irec *new, int *logflagsp);
xfs_extlen_t xfs_bmapi_minleft(struct xfs_trans *tp, struct xfs_inode *ip,
int fork);
enum xfs_bmap_intent_type {
XFS_BMAP_MAP = 1,

View File

@@ -213,18 +213,16 @@ xfs_bmbt_alloc_block(
if (args.fsbno == NULLFSBLOCK) {
args.fsbno = be64_to_cpu(start->l);
args.type = XFS_ALLOCTYPE_START_BNO;
/*
* Make sure there is sufficient room left in the AG to
* complete a full tree split for an extent insert. If
* we are converting the middle part of an extent then
* we may need space for two tree splits.
*
* We are relying on the caller to make the correct block
* reservation for this operation to succeed. If the
* reservation amount is insufficient then we may fail a
* block allocation here and corrupt the filesystem.
* If we are coming here from something like unwritten extent
* conversion, there has been no data extent allocation already
* done, so we have to ensure that we attempt to locate the
* entire set of bmbt allocations in the same AG, as
* xfs_bmapi_write() would have reserved.
*/
args.minleft = args.tp->t_blk_res;
args.minleft = xfs_bmapi_minleft(cur->bc_tp, cur->bc_ino.ip,
cur->bc_ino.whichfork);
} else if (cur->bc_tp->t_flags & XFS_TRANS_LOWMODE) {
args.type = XFS_ALLOCTYPE_START_BNO;
} else {
@@ -248,6 +246,7 @@ xfs_bmbt_alloc_block(
* successful activate the lowspace algorithm.
*/
args.fsbno = 0;
args.minleft = 0;
args.type = XFS_ALLOCTYPE_FIRST_AG;
error = xfs_alloc_vextent(&args);
if (error)

View File

@@ -2913,9 +2913,22 @@ xfs_btree_split_worker(
}
/*
* BMBT split requests often come in with little stack to work on. Push
* BMBT split requests often come in with little stack to work on so we push
* them off to a worker thread so there is lots of stack to use. For the other
* btree types, just call directly to avoid the context switch overhead here.
*
* Care must be taken here - the work queue rescuer thread introduces potential
* AGF <> worker queue deadlocks if the BMBT block allocation has to lock new
* AGFs to allocate blocks. A task being run by the rescuer could attempt to
* lock an AGF that is already locked by a task queued to run by the rescuer,
* resulting in an ABBA deadlock as the rescuer cannot run the lock holder to
* release it until the current thread it is running gains the lock.
*
* To avoid this issue, we only ever queue BMBT splits that don't have an AGF
* already locked to allocate from. The only place that doesn't hold an AGF
* locked is unwritten extent conversion at IO completion, but that has already
* been offloaded to a worker thread and hence has no stack consumption issues
* we have to worry about.
*/
STATIC int /* error */
xfs_btree_split(
@@ -2929,7 +2942,8 @@ xfs_btree_split(
struct xfs_btree_split_args args;
DECLARE_COMPLETION_ONSTACK(done);
if (cur->bc_btnum != XFS_BTNUM_BMAP)
if (cur->bc_btnum != XFS_BTNUM_BMAP ||
cur->bc_tp->t_firstblock == NULLFSBLOCK)
return __xfs_btree_split(cur, level, ptrp, key, curp, stat);
args.cur = cur;

View File

@@ -257,6 +257,8 @@ typedef struct xfs_fsop_resblks {
#define XFS_MAX_AG_BLOCKS (XFS_MAX_AG_BYTES / XFS_MIN_BLOCKSIZE)
#define XFS_MAX_CRC_AG_BLOCKS (XFS_MAX_AG_BYTES / XFS_MIN_CRC_BLOCKSIZE)
#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1))
/* keep the maximum size under 2^31 by a small amount */
#define XFS_MAX_LOG_BYTES \
((2 * 1024 * 1024 * 1024ULL) - XFS_MIN_LOG_BYTES)

View File

@@ -1737,6 +1737,7 @@ xfs_dialloc(
struct xfs_perag *pag;
struct xfs_ino_geometry *igeo = M_IGEO(mp);
bool ok_alloc = true;
bool low_space = false;
int flags;
xfs_ino_t ino;
@@ -1767,6 +1768,20 @@ xfs_dialloc(
ok_alloc = false;
}
/*
* If we are near to ENOSPC, we want to prefer allocation from AGs that
* have free inodes in them rather than use up free space allocating new
* inode chunks. Hence we turn off allocation for the first non-blocking
* pass through the AGs if we are near ENOSPC to consume free inodes
* that we can immediately allocate, but then we allow allocation on the
* second pass if we fail to find an AG with free inodes in it.
*/
if (percpu_counter_read_positive(&mp->m_fdblocks) <
mp->m_low_space[XFS_LOWSP_1_PCNT]) {
ok_alloc = false;
low_space = true;
}
/*
* Loop until we find an allocation group that either has free inodes
* or in which we can allocate some inodes. Iterate through the
@@ -1795,6 +1810,8 @@ xfs_dialloc(
break;
}
flags = 0;
if (low_space)
ok_alloc = true;
}
xfs_perag_put(pag);
}

View File

@@ -324,7 +324,6 @@ struct xfs_inode_log_format_32 {
#define XFS_ILOG_DOWNER 0x200 /* change the data fork owner on replay */
#define XFS_ILOG_AOWNER 0x400 /* change the attr fork owner on replay */
/*
* The timestamps are dirty, but not necessarily anything else in the inode
* core. Unlike the other fields above this one must never make it to disk
@@ -333,6 +332,14 @@ struct xfs_inode_log_format_32 {
*/
#define XFS_ILOG_TIMESTAMP 0x4000
/*
* The version field has been changed, but not necessarily anything else of
* interest. This must never make it to disk - it is used purely to ensure that
* the inode item ->precommit operation can update the fsync flag triggers
* in the inode item correctly.
*/
#define XFS_ILOG_IVERSION 0x8000
#define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \
XFS_ILOG_DBROOT | XFS_ILOG_DEV | \
XFS_ILOG_ADATA | XFS_ILOG_AEXT | \

View File

@@ -413,7 +413,6 @@ xfs_validate_sb_common(
sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
sbp->sb_inodelog > XFS_DINODE_MAX_LOG ||
sbp->sb_inodesize != (1 << sbp->sb_inodelog) ||
sbp->sb_logsunit > XLOG_MAX_RECORD_BSIZE ||
sbp->sb_inopblock != howmany(sbp->sb_blocksize,sbp->sb_inodesize) ||
XFS_FSB_TO_B(mp, sbp->sb_agblocks) < XFS_MIN_AG_BYTES ||
XFS_FSB_TO_B(mp, sbp->sb_agblocks) > XFS_MAX_AG_BYTES ||
@@ -431,6 +430,61 @@ xfs_validate_sb_common(
return -EFSCORRUPTED;
}
/*
* Logs that are too large are not supported at all. Reject them
* outright. Logs that are too small are tolerated on v4 filesystems,
* but we can only check that when mounting the log. Hence we skip
* those checks here.
*/
if (sbp->sb_logblocks > XFS_MAX_LOG_BLOCKS) {
xfs_notice(mp,
"Log size 0x%x blocks too large, maximum size is 0x%llx blocks",
sbp->sb_logblocks, XFS_MAX_LOG_BLOCKS);
return -EFSCORRUPTED;
}
if (XFS_FSB_TO_B(mp, sbp->sb_logblocks) > XFS_MAX_LOG_BYTES) {
xfs_warn(mp,
"log size 0x%llx bytes too large, maximum size is 0x%llx bytes",
XFS_FSB_TO_B(mp, sbp->sb_logblocks),
XFS_MAX_LOG_BYTES);
return -EFSCORRUPTED;
}
/*
* Do not allow filesystems with corrupted log sector or stripe units to
* be mounted. We cannot safely size the iclogs or write to the log if
* the log stripe unit is not valid.
*/
if (sbp->sb_versionnum & XFS_SB_VERSION_SECTORBIT) {
if (sbp->sb_logsectsize != (1U << sbp->sb_logsectlog)) {
xfs_notice(mp,
"log sector size in bytes/log2 (0x%x/0x%x) must match",
sbp->sb_logsectsize, 1U << sbp->sb_logsectlog);
return -EFSCORRUPTED;
}
} else if (sbp->sb_logsectsize || sbp->sb_logsectlog) {
xfs_notice(mp,
"log sector size in bytes/log2 (0x%x/0x%x) are not zero",
sbp->sb_logsectsize, sbp->sb_logsectlog);
return -EFSCORRUPTED;
}
if (sbp->sb_logsunit > 1) {
if (sbp->sb_logsunit % sbp->sb_blocksize) {
xfs_notice(mp,
"log stripe unit 0x%x bytes must be a multiple of block size",
sbp->sb_logsunit);
return -EFSCORRUPTED;
}
if (sbp->sb_logsunit > XLOG_MAX_RECORD_BSIZE) {
xfs_notice(mp,
"log stripe unit 0x%x bytes over maximum size (0x%x bytes)",
sbp->sb_logsunit, XLOG_MAX_RECORD_BSIZE);
return -EFSCORRUPTED;
}
}
/* Validate the realtime geometry; stolen from xfs_repair */
if (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE ||
sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) {

View File

@@ -40,9 +40,8 @@ xfs_trans_ijoin(
iip->ili_lock_flags = lock_flags;
ASSERT(!xfs_iflags_test(ip, XFS_ISTALE));
/*
* Get a log_item_desc to point at the new item.
*/
/* Reset the per-tx dirty context and add the item to the tx. */
iip->ili_dirty_flags = 0;
xfs_trans_add_item(tp, &iip->ili_item);
}
@@ -76,17 +75,10 @@ xfs_trans_ichgtime(
/*
* This is called to mark the fields indicated in fieldmask as needing to be
* logged when the transaction is committed. The inode must already be
* associated with the given transaction.
*
* The values for fieldmask are defined in xfs_inode_item.h. We always log all
* of the core inode if any of it has changed, and we always log all of the
* inline data/extents/b-tree root if any of them has changed.
*
* Grab and pin the cluster buffer associated with this inode to avoid RMW
* cycles at inode writeback time. Avoid the need to add error handling to every
* xfs_trans_log_inode() call by shutting down on read error. This will cause
* transactions to fail and everything to error out, just like if we return a
* read error in a dirty transaction and cancel it.
* associated with the given transaction. All we do here is record where the
* inode was dirtied and mark the transaction and inode log item dirty;
* everything else is done in the ->precommit log item operation after the
* changes in the transaction have been completed.
*/
void
xfs_trans_log_inode(
@@ -96,7 +88,6 @@ xfs_trans_log_inode(
{
struct xfs_inode_log_item *iip = ip->i_itemp;
struct inode *inode = VFS_I(ip);
uint iversion_flags = 0;
ASSERT(iip);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -104,18 +95,6 @@ xfs_trans_log_inode(
tp->t_flags |= XFS_TRANS_DIRTY;
/*
* Don't bother with i_lock for the I_DIRTY_TIME check here, as races
* don't matter - we either will need an extra transaction in 24 hours
* to log the timestamps, or will clear already cleared fields in the
* worst case.
*/
if (inode->i_state & I_DIRTY_TIME) {
spin_lock(&inode->i_lock);
inode->i_state &= ~I_DIRTY_TIME;
spin_unlock(&inode->i_lock);
}
/*
* First time we log the inode in a transaction, bump the inode change
* counter if it is configured for this to occur. While we have the
@@ -128,86 +107,10 @@ xfs_trans_log_inode(
if (!test_and_set_bit(XFS_LI_DIRTY, &iip->ili_item.li_flags)) {
if (IS_I_VERSION(inode) &&
inode_maybe_inc_iversion(inode, flags & XFS_ILOG_CORE))
iversion_flags = XFS_ILOG_CORE;
flags |= XFS_ILOG_IVERSION;
}
/*
* If we're updating the inode core or the timestamps and it's possible
* to upgrade this inode to bigtime format, do so now.
*/
if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) &&
xfs_has_bigtime(ip->i_mount) &&
!xfs_inode_has_bigtime(ip)) {
ip->i_diflags2 |= XFS_DIFLAG2_BIGTIME;
flags |= XFS_ILOG_CORE;
}
/*
* Inode verifiers do not check that the extent size hint is an integer
* multiple of the rt extent size on a directory with both rtinherit
* and extszinherit flags set. If we're logging a directory that is
* misconfigured in this way, clear the hint.
*/
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
(ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) {
ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
XFS_DIFLAG_EXTSZINHERIT);
ip->i_extsize = 0;
flags |= XFS_ILOG_CORE;
}
/*
* Record the specific change for fdatasync optimisation. This allows
* fdatasync to skip log forces for inodes that are only timestamp
* dirty.
*/
spin_lock(&iip->ili_lock);
iip->ili_fsync_fields |= flags;
if (!iip->ili_item.li_buf) {
struct xfs_buf *bp;
int error;
/*
* We hold the ILOCK here, so this inode is not going to be
* flushed while we are here. Further, because there is no
* buffer attached to the item, we know that there is no IO in
* progress, so nothing will clear the ili_fields while we read
* in the buffer. Hence we can safely drop the spin lock and
* read the buffer knowing that the state will not change from
* here.
*/
spin_unlock(&iip->ili_lock);
error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &bp);
if (error) {
xfs_force_shutdown(ip->i_mount, SHUTDOWN_META_IO_ERROR);
return;
}
/*
* We need an explicit buffer reference for the log item but
* don't want the buffer to remain attached to the transaction.
* Hold the buffer but release the transaction reference once
* we've attached the inode log item to the buffer log item
* list.
*/
xfs_buf_hold(bp);
spin_lock(&iip->ili_lock);
iip->ili_item.li_buf = bp;
bp->b_flags |= _XBF_INODES;
list_add_tail(&iip->ili_item.li_bio_list, &bp->b_li_list);
xfs_trans_brelse(tp, bp);
}
/*
* Always OR in the bits from the ili_last_fields field. This is to
* coordinate with the xfs_iflush() and xfs_buf_inode_iodone() routines
* in the eventual clearing of the ili_fields bits. See the big comment
* in xfs_iflush() for an explanation of this coordination mechanism.
*/
iip->ili_fields |= (flags | iip->ili_last_fields | iversion_flags);
spin_unlock(&iip->ili_lock);
iip->ili_dirty_flags |= flags;
}
int

View File

@@ -333,7 +333,6 @@ xfs_attr_inactive(
int error = 0;
mp = dp->i_mount;
ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
xfs_ilock(dp, lock_mode);
if (!xfs_inode_has_attr_fork(dp))

View File

@@ -314,15 +314,13 @@ xfs_getbmap_report_one(
if (isnullstartblock(got->br_startblock) ||
got->br_startblock == DELAYSTARTBLOCK) {
/*
* Delalloc extents that start beyond EOF can occur due to
* speculative EOF allocation when the delalloc extent is larger
* than the largest freespace extent at conversion time. These
* extents cannot be converted by data writeback, so can exist
* here even if we are not supposed to be finding delalloc
* extents.
* Take the flush completion as being a point-in-time snapshot
* where there are no delalloc extents, and if any new ones
* have been created racily, just skip them as being 'after'
* the flush and so don't get reported.
*/
if (got->br_startoff < XFS_B_TO_FSB(ip->i_mount, XFS_ISIZE(ip)))
ASSERT((bmv->bmv_iflags & BMV_IF_DELALLOC) != 0);
if (!(bmv->bmv_iflags & BMV_IF_DELALLOC))
return 0;
p->bmv_oflags |= BMV_OF_DELALLOC;
p->bmv_block = -2;
@@ -560,7 +558,9 @@ xfs_getbmap(
if (!xfs_iext_next_extent(ifp, &icur, &got)) {
xfs_fileoff_t end = XFS_B_TO_FSB(mp, XFS_ISIZE(ip));
out[bmv->bmv_entries - 1].bmv_oflags |= BMV_OF_LAST;
if (bmv->bmv_entries > 0)
out[bmv->bmv_entries - 1].bmv_oflags |=
BMV_OF_LAST;
if (whichfork != XFS_ATTR_FORK && bno < end &&
!xfs_getbmap_full(bmv)) {

View File

@@ -452,10 +452,18 @@ xfs_buf_item_format(
* This is called to pin the buffer associated with the buf log item in memory
* so it cannot be written out.
*
* We also always take a reference to the buffer log item here so that the bli
* is held while the item is pinned in memory. This means that we can
* unconditionally drop the reference count a transaction holds when the
* transaction is completed.
* We take a reference to the buffer log item here so that the BLI life cycle
* extends at least until the buffer is unpinned via xfs_buf_item_unpin() and
* inserted into the AIL.
*
* We also need to take a reference to the buffer itself as the BLI unpin
* processing requires accessing the buffer after the BLI has dropped the final
* BLI reference. See xfs_buf_item_unpin() for an explanation.
* If unpins race to drop the final BLI reference and only the
* BLI owns a reference to the buffer, then the loser of the race can have the
* buffer fgreed from under it (e.g. on shutdown). Taking a buffer reference per
* pin count ensures the life cycle of the buffer extends for as
* long as we hold the buffer pin reference in xfs_buf_item_unpin().
*/
STATIC void
xfs_buf_item_pin(
@@ -470,13 +478,30 @@ xfs_buf_item_pin(
trace_xfs_buf_item_pin(bip);
xfs_buf_hold(bip->bli_buf);
atomic_inc(&bip->bli_refcount);
atomic_inc(&bip->bli_buf->b_pin_count);
}
/*
* This is called to unpin the buffer associated with the buf log item which
* was previously pinned with a call to xfs_buf_item_pin().
* This is called to unpin the buffer associated with the buf log item which was
* previously pinned with a call to xfs_buf_item_pin(). We enter this function
* with a buffer pin count, a buffer reference and a BLI reference.
*
* We must drop the BLI reference before we unpin the buffer because the AIL
* doesn't acquire a BLI reference whenever it accesses it. Therefore if the
* refcount drops to zero, the bli could still be AIL resident and the buffer
* submitted for I/O at any point before we return. This can result in IO
* completion freeing the buffer while we are still trying to access it here.
* This race condition can also occur in shutdown situations where we abort and
* unpin buffers from contexts other that journal IO completion.
*
* Hence we have to hold a buffer reference per pin count to ensure that the
* buffer cannot be freed until we have finished processing the unpin operation.
* The reference is taken in xfs_buf_item_pin(), and we must hold it until we
* are done processing the buffer state. In the case of an abort (remove =
* true) then we re-use the current pin reference as the IO reference we hand
* off to IO failure handling.
*/
STATIC void
xfs_buf_item_unpin(
@@ -493,24 +518,18 @@ xfs_buf_item_unpin(
trace_xfs_buf_item_unpin(bip);
/*
* Drop the bli ref associated with the pin and grab the hold required
* for the I/O simulation failure in the abort case. We have to do this
* before the pin count drops because the AIL doesn't acquire a bli
* reference. Therefore if the refcount drops to zero, the bli could
* still be AIL resident and the buffer submitted for I/O (and freed on
* completion) at any point before we return. This can be removed once
* the AIL properly holds a reference on the bli.
*/
freed = atomic_dec_and_test(&bip->bli_refcount);
if (freed && !stale && remove)
xfs_buf_hold(bp);
if (atomic_dec_and_test(&bp->b_pin_count))
wake_up_all(&bp->b_waiters);
/* nothing to do but drop the pin count if the bli is active */
if (!freed)
/*
* Nothing to do but drop the buffer pin reference if the BLI is
* still active.
*/
if (!freed) {
xfs_buf_rele(bp);
return;
}
if (stale) {
ASSERT(bip->bli_flags & XFS_BLI_STALE);
@@ -522,6 +541,15 @@ xfs_buf_item_unpin(
trace_xfs_buf_item_unpin_stale(bip);
/*
* The buffer has been locked and referenced since it was marked
* stale so we own both lock and reference exclusively here. We
* do not need the pin reference any more, so drop it now so
* that we only have one reference to drop once item completion
* processing is complete.
*/
xfs_buf_rele(bp);
/*
* If we get called here because of an IO error, we may or may
* not have the item on the AIL. xfs_trans_ail_delete() will
@@ -538,16 +566,30 @@ xfs_buf_item_unpin(
ASSERT(bp->b_log_item == NULL);
}
xfs_buf_relse(bp);
} else if (remove) {
return;
}
if (remove) {
/*
* The buffer must be locked and held by the caller to simulate
* an async I/O failure. We acquired the hold for this case
* before the buffer was unpinned.
* We need to simulate an async IO failures here to ensure that
* the correct error completion is run on this buffer. This
* requires a reference to the buffer and for the buffer to be
* locked. We can safely pass ownership of the pin reference to
* the IO to ensure that nothing can free the buffer while we
* wait for the lock and then run the IO failure completion.
*/
xfs_buf_lock(bp);
bp->b_flags |= XBF_ASYNC;
xfs_buf_ioend_fail(bp);
return;
}
/*
* BLI has no more active references - it will be moved to the AIL to
* manage the remaining BLI/buffer life cycle. There is nothing left for
* us to do here so drop the pin reference to the buffer.
*/
xfs_buf_rele(bp);
}
STATIC uint

View File

@@ -798,7 +798,6 @@ xfs_qm_dqget_cache_insert(
error = radix_tree_insert(tree, id, dqp);
if (unlikely(error)) {
/* Duplicate found! Caller must try again. */
WARN_ON(error != -EEXIST);
mutex_unlock(&qi->qi_tree_lock);
trace_xfs_dqget_dup(dqp);
return error;

View File

@@ -146,6 +146,20 @@ xfs_nfs_get_inode(
return ERR_PTR(error);
}
/*
* Reload the incore unlinked list to avoid failure in inodegc.
* Use an unlocked check here because unrecovered unlinked inodes
* should be somewhat rare.
*/
if (xfs_inode_unlinked_incomplete(ip)) {
error = xfs_inode_reload_unlinked(ip);
if (error) {
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
xfs_irele(ip);
return ERR_PTR(error);
}
}
if (VFS_I(ip)->i_generation != generation) {
xfs_irele(ip);
return ERR_PTR(-ESTALE);

View File

@@ -236,6 +236,7 @@ xfs_extent_busy_update_extent(
*
*/
busyp->bno = fend;
busyp->length = bend - fend;
} else if (bbno < fbno) {
/*
* Case 8:

View File

@@ -761,6 +761,7 @@ xfs_getfsmap_datadev_bnobt(
{
struct xfs_alloc_rec_incore akeys[2];
memset(akeys, 0, sizeof(akeys));
info->missing_owner = XFS_FMR_OWN_UNKNOWN;
return __xfs_getfsmap_datadev(tp, keys, info,
xfs_getfsmap_datadev_bnobt_query, &akeys[0]);

View File

@@ -115,11 +115,16 @@ xfs_growfs_data_private(
nb_div = nb;
nb_mod = do_div(nb_div, mp->m_sb.sb_agblocks);
nagcount = nb_div + (nb_mod != 0);
if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
nagcount--;
nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
if (nb_mod && nb_mod >= XFS_MIN_AG_BLOCKS)
nb_div++;
else if (nb_mod)
nb = nb_div * mp->m_sb.sb_agblocks;
if (nb_div > XFS_MAX_AGNUMBER + 1) {
nb_div = XFS_MAX_AGNUMBER + 1;
nb = nb_div * mp->m_sb.sb_agblocks;
}
nagcount = nb_div;
delta = nb - mp->m_sb.sb_dblocks;
/*
* Reject filesystems with a single AG because they are not

View File

@@ -113,7 +113,7 @@ xfs_inode_alloc(
INIT_LIST_HEAD(&ip->i_ioend_list);
spin_lock_init(&ip->i_ioend_lock);
ip->i_next_unlinked = NULLAGINO;
ip->i_prev_unlinked = NULLAGINO;
ip->i_prev_unlinked = 0;
return ip;
}
@@ -454,6 +454,27 @@ xfs_inodegc_queue_all(
return ret;
}
/* Wait for all queued work and collect errors */
static int
xfs_inodegc_wait_all(
struct xfs_mount *mp)
{
int cpu;
int error = 0;
flush_workqueue(mp->m_inodegc_wq);
for_each_online_cpu(cpu) {
struct xfs_inodegc *gc;
gc = per_cpu_ptr(mp->m_inodegc, cpu);
if (gc->error && !error)
error = gc->error;
gc->error = 0;
}
return error;
}
/*
* Check the validity of the inode we just found it the cache
*/
@@ -1490,15 +1511,14 @@ xfs_blockgc_free_space(
if (error)
return error;
xfs_inodegc_flush(mp);
return 0;
return xfs_inodegc_flush(mp);
}
/*
* Reclaim all the free space that we can by scheduling the background blockgc
* and inodegc workers immediately and waiting for them all to clear.
*/
void
int
xfs_blockgc_flush_all(
struct xfs_mount *mp)
{
@@ -1519,7 +1539,7 @@ xfs_blockgc_flush_all(
for_each_perag_tag(mp, agno, pag, XFS_ICI_BLOCKGC_TAG)
flush_delayed_work(&pag->pag_blockgc_work);
xfs_inodegc_flush(mp);
return xfs_inodegc_flush(mp);
}
/*
@@ -1841,13 +1861,17 @@ xfs_inodegc_set_reclaimable(
* This is the last chance to make changes to an otherwise unreferenced file
* before incore reclamation happens.
*/
static void
static int
xfs_inodegc_inactivate(
struct xfs_inode *ip)
{
int error;
trace_xfs_inode_inactivating(ip);
xfs_inactive(ip);
error = xfs_inactive(ip);
xfs_inodegc_set_reclaimable(ip);
return error;
}
void
@@ -1858,6 +1882,7 @@ xfs_inodegc_worker(
struct xfs_inodegc, work);
struct llist_node *node = llist_del_all(&gc->list);
struct xfs_inode *ip, *n;
unsigned int nofs_flag;
ASSERT(gc->cpu == smp_processor_id());
@@ -1866,14 +1891,27 @@ xfs_inodegc_worker(
if (!node)
return;
/*
* We can allocate memory here while doing writeback on behalf of
* memory reclaim. To avoid memory allocation deadlocks set the
* task-wide nofs context for the following operations.
*/
nofs_flag = memalloc_nofs_save();
ip = llist_entry(node, struct xfs_inode, i_gclist);
trace_xfs_inodegc_worker(ip->i_mount, READ_ONCE(gc->shrinker_hits));
WRITE_ONCE(gc->shrinker_hits, 0);
llist_for_each_entry_safe(ip, n, node, i_gclist) {
int error;
xfs_iflags_set(ip, XFS_INACTIVATING);
xfs_inodegc_inactivate(ip);
error = xfs_inodegc_inactivate(ip);
if (error && !gc->error)
gc->error = error;
}
memalloc_nofs_restore(nofs_flag);
}
/*
@@ -1894,13 +1932,13 @@ xfs_inodegc_push(
* Force all currently queued inode inactivation work to run immediately and
* wait for the work to finish.
*/
void
int
xfs_inodegc_flush(
struct xfs_mount *mp)
{
xfs_inodegc_push(mp);
trace_xfs_inodegc_flush(mp, __return_address);
flush_workqueue(mp->m_inodegc_wq);
return xfs_inodegc_wait_all(mp);
}
/*

View File

@@ -59,7 +59,7 @@ int xfs_blockgc_free_dquots(struct xfs_mount *mp, struct xfs_dquot *udqp,
unsigned int iwalk_flags);
int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int iwalk_flags);
int xfs_blockgc_free_space(struct xfs_mount *mp, struct xfs_icwalk *icm);
void xfs_blockgc_flush_all(struct xfs_mount *mp);
int xfs_blockgc_flush_all(struct xfs_mount *mp);
void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip);
@@ -77,7 +77,7 @@ void xfs_blockgc_start(struct xfs_mount *mp);
void xfs_inodegc_worker(struct work_struct *work);
void xfs_inodegc_push(struct xfs_mount *mp);
void xfs_inodegc_flush(struct xfs_mount *mp);
int xfs_inodegc_flush(struct xfs_mount *mp);
void xfs_inodegc_stop(struct xfs_mount *mp);
void xfs_inodegc_start(struct xfs_mount *mp);
void xfs_inodegc_cpu_dead(struct xfs_mount *mp, unsigned int cpu);

View File

@@ -1620,16 +1620,7 @@ xfs_inactive_ifree(
*/
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1);
/*
* Just ignore errors at this point. There is nothing we can do except
* to try to keep going. Make sure it's not a silent error.
*/
error = xfs_trans_commit(tp);
if (error)
xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
__func__, error);
return 0;
return xfs_trans_commit(tp);
}
/*
@@ -1696,12 +1687,12 @@ xfs_inode_needs_inactive(
* now be truncated. Also, we clear all of the read-ahead state
* kept for the inode here since the file is now closed.
*/
void
int
xfs_inactive(
xfs_inode_t *ip)
{
struct xfs_mount *mp;
int error;
int error = 0;
int truncate = 0;
/*
@@ -1742,7 +1733,7 @@ xfs_inactive(
* reference to the inode at this point anyways.
*/
if (xfs_can_free_eofblocks(ip, true))
xfs_free_eofblocks(ip);
error = xfs_free_eofblocks(ip);
goto out;
}
@@ -1752,9 +1743,21 @@ xfs_inactive(
ip->i_df.if_nextents > 0 || ip->i_delayed_blks > 0))
truncate = 1;
error = xfs_qm_dqattach(ip);
if (error)
goto out;
if (xfs_iflags_test(ip, XFS_IQUOTAUNCHECKED)) {
/*
* If this inode is being inactivated during a quotacheck and
* has not yet been scanned by quotacheck, we /must/ remove
* the dquots from the inode before inactivation changes the
* block and inode counts. Most probably this is a result of
* reloading the incore iunlinked list to purge unrecovered
* unlinked inodes.
*/
xfs_qm_dqdetach(ip);
} else {
error = xfs_qm_dqattach(ip);
if (error)
goto out;
}
if (S_ISLNK(VFS_I(ip)->i_mode))
error = xfs_inactive_symlink(ip);
@@ -1779,7 +1782,7 @@ xfs_inactive(
/*
* Free the inode.
*/
xfs_inactive_ifree(ip);
error = xfs_inactive_ifree(ip);
out:
/*
@@ -1787,6 +1790,7 @@ out:
* the attached dquots.
*/
xfs_qm_dqdetach(ip);
return error;
}
/*
@@ -1837,12 +1841,17 @@ xfs_iunlink_lookup(
rcu_read_lock();
ip = radix_tree_lookup(&pag->pag_ici_root, agino);
if (!ip) {
/* Caller can handle inode not being in memory. */
rcu_read_unlock();
return NULL;
}
/*
* Inode not in memory or in RCU freeing limbo should not happen.
* Warn about this and let the caller handle the failure.
* Inode in RCU freeing limbo should not happen. Warn about this and
* let the caller handle the failure.
*/
if (WARN_ON_ONCE(!ip || !ip->i_ino)) {
if (WARN_ON_ONCE(!ip->i_ino)) {
rcu_read_unlock();
return NULL;
}
@@ -1851,7 +1860,10 @@ xfs_iunlink_lookup(
return ip;
}
/* Update the prev pointer of the next agino. */
/*
* Update the prev pointer of the next agino. Returns -ENOLINK if the inode
* is not in cache.
*/
static int
xfs_iunlink_update_backref(
struct xfs_perag *pag,
@@ -1866,7 +1878,8 @@ xfs_iunlink_update_backref(
ip = xfs_iunlink_lookup(pag, next_agino);
if (!ip)
return -EFSCORRUPTED;
return -ENOLINK;
ip->i_prev_unlinked = prev_agino;
return 0;
}
@@ -1910,6 +1923,64 @@ xfs_iunlink_update_bucket(
return 0;
}
/*
* Load the inode @next_agino into the cache and set its prev_unlinked pointer
* to @prev_agino. Caller must hold the AGI to synchronize with other changes
* to the unlinked list.
*/
STATIC int
xfs_iunlink_reload_next(
struct xfs_trans *tp,
struct xfs_buf *agibp,
xfs_agino_t prev_agino,
xfs_agino_t next_agino)
{
struct xfs_perag *pag = agibp->b_pag;
struct xfs_mount *mp = pag->pag_mount;
struct xfs_inode *next_ip = NULL;
xfs_ino_t ino;
int error;
ASSERT(next_agino != NULLAGINO);
#ifdef DEBUG
rcu_read_lock();
next_ip = radix_tree_lookup(&pag->pag_ici_root, next_agino);
ASSERT(next_ip == NULL);
rcu_read_unlock();
#endif
xfs_info_ratelimited(mp,
"Found unrecovered unlinked inode 0x%x in AG 0x%x. Initiating recovery.",
next_agino, pag->pag_agno);
/*
* Use an untrusted lookup just to be cautious in case the AGI has been
* corrupted and now points at a free inode. That shouldn't happen,
* but we'd rather shut down now since we're already running in a weird
* situation.
*/
ino = XFS_AGINO_TO_INO(mp, pag->pag_agno, next_agino);
error = xfs_iget(mp, tp, ino, XFS_IGET_UNTRUSTED, 0, &next_ip);
if (error)
return error;
/* If this is not an unlinked inode, something is very wrong. */
if (VFS_I(next_ip)->i_nlink != 0) {
error = -EFSCORRUPTED;
goto rele;
}
next_ip->i_prev_unlinked = prev_agino;
trace_xfs_iunlink_reload_next(next_ip);
rele:
ASSERT(!(VFS_I(next_ip)->i_state & I_DONTCACHE));
if (xfs_is_quotacheck_running(mp) && next_ip)
xfs_iflags_set(next_ip, XFS_IQUOTAUNCHECKED);
xfs_irele(next_ip);
return error;
}
static int
xfs_iunlink_insert_inode(
struct xfs_trans *tp,
@@ -1941,6 +2012,8 @@ xfs_iunlink_insert_inode(
* inode.
*/
error = xfs_iunlink_update_backref(pag, agino, next_agino);
if (error == -ENOLINK)
error = xfs_iunlink_reload_next(tp, agibp, agino, next_agino);
if (error)
return error;
@@ -1956,6 +2029,7 @@ xfs_iunlink_insert_inode(
}
/* Point the head of the list to point to this inode. */
ip->i_prev_unlinked = NULLAGINO;
return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
}
@@ -2035,6 +2109,9 @@ xfs_iunlink_remove_inode(
*/
error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked,
ip->i_next_unlinked);
if (error == -ENOLINK)
error = xfs_iunlink_reload_next(tp, agibp, ip->i_prev_unlinked,
ip->i_next_unlinked);
if (error)
return error;
@@ -2055,7 +2132,7 @@ xfs_iunlink_remove_inode(
}
ip->i_next_unlinked = NULLAGINO;
ip->i_prev_unlinked = NULLAGINO;
ip->i_prev_unlinked = 0;
return error;
}
@@ -2235,11 +2312,26 @@ xfs_ifree_cluster(
* This buffer may not have been correctly initialised as we
* didn't read it from disk. That's not important because we are
* only using to mark the buffer as stale in the log, and to
* attach stale cached inodes on it. That means it will never be
* dispatched for IO. If it is, we want to know about it, and we
* want it to fail. We can acheive this by adding a write
* verifier to the buffer.
* attach stale cached inodes on it.
*
* For the inode that triggered the cluster freeing, this
* attachment may occur in xfs_inode_item_precommit() after we
* have marked this buffer stale. If this buffer was not in
* memory before xfs_ifree_cluster() started, it will not be
* marked XBF_DONE and this will cause problems later in
* xfs_inode_item_precommit() when we trip over a (stale, !done)
* buffer to attached to the transaction.
*
* Hence we have to mark the buffer as XFS_DONE here. This is
* safe because we are also marking the buffer as XBF_STALE and
* XFS_BLI_STALE. That means it will never be dispatched for
* IO and it won't be unlocked until the cluster freeing has
* been committed to the journal and the buffer unpinned. If it
* is written, we want to know about it, and we want it to
* fail. We can acheive this by adding a write verifier to the
* buffer.
*/
bp->b_flags |= XBF_DONE;
bp->b_ops = &xfs_inode_buf_ops;
/*
@@ -3544,3 +3636,117 @@ xfs_iunlock2_io_mmap(
if (ip1 != ip2)
inode_unlock(VFS_I(ip1));
}
/*
* Reload the incore inode list for this inode. Caller should ensure that
* the link count cannot change, either by taking ILOCK_SHARED or otherwise
* preventing other threads from executing.
*/
int
xfs_inode_reload_unlinked_bucket(
struct xfs_trans *tp,
struct xfs_inode *ip)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *agibp;
struct xfs_agi *agi;
struct xfs_perag *pag;
xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
xfs_agino_t prev_agino, next_agino;
unsigned int bucket;
bool foundit = false;
int error;
/* Grab the first inode in the list */
pag = xfs_perag_get(mp, agno);
error = xfs_ialloc_read_agi(pag, tp, &agibp);
xfs_perag_put(pag);
if (error)
return error;
/*
* We've taken ILOCK_SHARED and the AGI buffer lock to stabilize the
* incore unlinked list pointers for this inode. Check once more to
* see if we raced with anyone else to reload the unlinked list.
*/
if (!xfs_inode_unlinked_incomplete(ip)) {
foundit = true;
goto out_agibp;
}
bucket = agino % XFS_AGI_UNLINKED_BUCKETS;
agi = agibp->b_addr;
trace_xfs_inode_reload_unlinked_bucket(ip);
xfs_info_ratelimited(mp,
"Found unrecovered unlinked inode 0x%x in AG 0x%x. Initiating list recovery.",
agino, agno);
prev_agino = NULLAGINO;
next_agino = be32_to_cpu(agi->agi_unlinked[bucket]);
while (next_agino != NULLAGINO) {
struct xfs_inode *next_ip = NULL;
/* Found this caller's inode, set its backlink. */
if (next_agino == agino) {
next_ip = ip;
next_ip->i_prev_unlinked = prev_agino;
foundit = true;
goto next_inode;
}
/* Try in-memory lookup first. */
next_ip = xfs_iunlink_lookup(pag, next_agino);
if (next_ip)
goto next_inode;
/* Inode not in memory, try reloading it. */
error = xfs_iunlink_reload_next(tp, agibp, prev_agino,
next_agino);
if (error)
break;
/* Grab the reloaded inode. */
next_ip = xfs_iunlink_lookup(pag, next_agino);
if (!next_ip) {
/* No incore inode at all? We reloaded it... */
ASSERT(next_ip != NULL);
error = -EFSCORRUPTED;
break;
}
next_inode:
prev_agino = next_agino;
next_agino = next_ip->i_next_unlinked;
}
out_agibp:
xfs_trans_brelse(tp, agibp);
/* Should have found this inode somewhere in the iunlinked bucket. */
if (!error && !foundit)
error = -EFSCORRUPTED;
return error;
}
/* Decide if this inode is missing its unlinked list and reload it. */
int
xfs_inode_reload_unlinked(
struct xfs_inode *ip)
{
struct xfs_trans *tp;
int error;
error = xfs_trans_alloc_empty(ip->i_mount, &tp);
if (error)
return error;
xfs_ilock(ip, XFS_ILOCK_SHARED);
if (xfs_inode_unlinked_incomplete(ip))
error = xfs_inode_reload_unlinked_bucket(tp, ip);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
xfs_trans_cancel(tp);
return error;
}

View File

@@ -68,8 +68,21 @@ typedef struct xfs_inode {
uint64_t i_diflags2; /* XFS_DIFLAG2_... */
struct timespec64 i_crtime; /* time created */
/* unlinked list pointers */
/*
* Unlinked list pointers. These point to the next and previous inodes
* in the AGI unlinked bucket list, respectively. These fields can
* only be updated with the AGI locked.
*
* i_next_unlinked caches di_next_unlinked.
*/
xfs_agino_t i_next_unlinked;
/*
* If the inode is not on an unlinked list, this field is zero. If the
* inode is the first element in an unlinked list, this field is
* NULLAGINO. Otherwise, i_prev_unlinked points to the previous inode
* in the unlinked list.
*/
xfs_agino_t i_prev_unlinked;
/* VFS inode */
@@ -81,6 +94,11 @@ typedef struct xfs_inode {
struct list_head i_ioend_list;
} xfs_inode_t;
static inline bool xfs_inode_on_unlinked_list(const struct xfs_inode *ip)
{
return ip->i_prev_unlinked != 0;
}
static inline bool xfs_inode_has_attr_fork(struct xfs_inode *ip)
{
return ip->i_forkoff > 0;
@@ -326,6 +344,9 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
*/
#define XFS_INACTIVATING (1 << 13)
/* Quotacheck is running but inode has not been added to quota counts. */
#define XFS_IQUOTAUNCHECKED (1 << 14)
/* All inode state flags related to inode reclaim. */
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
XFS_IRECLAIM | \
@@ -340,7 +361,7 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
#define XFS_IRECLAIM_RESET_FLAGS \
(XFS_IRECLAIMABLE | XFS_IRECLAIM | \
XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | XFS_NEED_INACTIVE | \
XFS_INACTIVATING)
XFS_INACTIVATING | XFS_IQUOTAUNCHECKED)
/*
* Flags for inode locking.
@@ -470,7 +491,7 @@ enum layout_break_reason {
(xfs_has_grpid((pip)->i_mount) || (VFS_I(pip)->i_mode & S_ISGID))
int xfs_release(struct xfs_inode *ip);
void xfs_inactive(struct xfs_inode *ip);
int xfs_inactive(struct xfs_inode *ip);
int xfs_lookup(struct xfs_inode *dp, const struct xfs_name *name,
struct xfs_inode **ipp, struct xfs_name *ci_name);
int xfs_create(struct user_namespace *mnt_userns,
@@ -575,4 +596,13 @@ void xfs_end_io(struct work_struct *work);
int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
static inline bool
xfs_inode_unlinked_incomplete(
struct xfs_inode *ip)
{
return VFS_I(ip)->i_nlink == 0 && !xfs_inode_on_unlinked_list(ip);
}
int xfs_inode_reload_unlinked_bucket(struct xfs_trans *tp, struct xfs_inode *ip);
int xfs_inode_reload_unlinked(struct xfs_inode *ip);
#endif /* __XFS_INODE_H__ */

View File

@@ -29,6 +29,153 @@ static inline struct xfs_inode_log_item *INODE_ITEM(struct xfs_log_item *lip)
return container_of(lip, struct xfs_inode_log_item, ili_item);
}
static uint64_t
xfs_inode_item_sort(
struct xfs_log_item *lip)
{
return INODE_ITEM(lip)->ili_inode->i_ino;
}
/*
* Prior to finally logging the inode, we have to ensure that all the
* per-modification inode state changes are applied. This includes VFS inode
* state updates, format conversions, verifier state synchronisation and
* ensuring the inode buffer remains in memory whilst the inode is dirty.
*
* We have to be careful when we grab the inode cluster buffer due to lock
* ordering constraints. The unlinked inode modifications (xfs_iunlink_item)
* require AGI -> inode cluster buffer lock order. The inode cluster buffer is
* not locked until ->precommit, so it happens after everything else has been
* modified.
*
* Further, we have AGI -> AGF lock ordering, and with O_TMPFILE handling we
* have AGI -> AGF -> iunlink item -> inode cluster buffer lock order. Hence we
* cannot safely lock the inode cluster buffer in xfs_trans_log_inode() because
* it can be called on a inode (e.g. via bumplink/droplink) before we take the
* AGF lock modifying directory blocks.
*
* Rather than force a complete rework of all the transactions to call
* xfs_trans_log_inode() once and once only at the end of every transaction, we
* move the pinning of the inode cluster buffer to a ->precommit operation. This
* matches how the xfs_iunlink_item locks the inode cluster buffer, and it
* ensures that the inode cluster buffer locking is always done last in a
* transaction. i.e. we ensure the lock order is always AGI -> AGF -> inode
* cluster buffer.
*
* If we return the inode number as the precommit sort key then we'll also
* guarantee that the order all inode cluster buffer locking is the same all the
* inodes and unlink items in the transaction.
*/
static int
xfs_inode_item_precommit(
struct xfs_trans *tp,
struct xfs_log_item *lip)
{
struct xfs_inode_log_item *iip = INODE_ITEM(lip);
struct xfs_inode *ip = iip->ili_inode;
struct inode *inode = VFS_I(ip);
unsigned int flags = iip->ili_dirty_flags;
/*
* Don't bother with i_lock for the I_DIRTY_TIME check here, as races
* don't matter - we either will need an extra transaction in 24 hours
* to log the timestamps, or will clear already cleared fields in the
* worst case.
*/
if (inode->i_state & I_DIRTY_TIME) {
spin_lock(&inode->i_lock);
inode->i_state &= ~I_DIRTY_TIME;
spin_unlock(&inode->i_lock);
}
/*
* If we're updating the inode core or the timestamps and it's possible
* to upgrade this inode to bigtime format, do so now.
*/
if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) &&
xfs_has_bigtime(ip->i_mount) &&
!xfs_inode_has_bigtime(ip)) {
ip->i_diflags2 |= XFS_DIFLAG2_BIGTIME;
flags |= XFS_ILOG_CORE;
}
/*
* Inode verifiers do not check that the extent size hint is an integer
* multiple of the rt extent size on a directory with both rtinherit
* and extszinherit flags set. If we're logging a directory that is
* misconfigured in this way, clear the hint.
*/
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
(ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) {
ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
XFS_DIFLAG_EXTSZINHERIT);
ip->i_extsize = 0;
flags |= XFS_ILOG_CORE;
}
/*
* Record the specific change for fdatasync optimisation. This allows
* fdatasync to skip log forces for inodes that are only timestamp
* dirty. Once we've processed the XFS_ILOG_IVERSION flag, convert it
* to XFS_ILOG_CORE so that the actual on-disk dirty tracking
* (ili_fields) correctly tracks that the version has changed.
*/
spin_lock(&iip->ili_lock);
iip->ili_fsync_fields |= (flags & ~XFS_ILOG_IVERSION);
if (flags & XFS_ILOG_IVERSION)
flags = ((flags & ~XFS_ILOG_IVERSION) | XFS_ILOG_CORE);
if (!iip->ili_item.li_buf) {
struct xfs_buf *bp;
int error;
/*
* We hold the ILOCK here, so this inode is not going to be
* flushed while we are here. Further, because there is no
* buffer attached to the item, we know that there is no IO in
* progress, so nothing will clear the ili_fields while we read
* in the buffer. Hence we can safely drop the spin lock and
* read the buffer knowing that the state will not change from
* here.
*/
spin_unlock(&iip->ili_lock);
error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &bp);
if (error)
return error;
/*
* We need an explicit buffer reference for the log item but
* don't want the buffer to remain attached to the transaction.
* Hold the buffer but release the transaction reference once
* we've attached the inode log item to the buffer log item
* list.
*/
xfs_buf_hold(bp);
spin_lock(&iip->ili_lock);
iip->ili_item.li_buf = bp;
bp->b_flags |= _XBF_INODES;
list_add_tail(&iip->ili_item.li_bio_list, &bp->b_li_list);
xfs_trans_brelse(tp, bp);
}
/*
* Always OR in the bits from the ili_last_fields field. This is to
* coordinate with the xfs_iflush() and xfs_buf_inode_iodone() routines
* in the eventual clearing of the ili_fields bits. See the big comment
* in xfs_iflush() for an explanation of this coordination mechanism.
*/
iip->ili_fields |= (flags | iip->ili_last_fields);
spin_unlock(&iip->ili_lock);
/*
* We are done with the log item transaction dirty state, so clear it so
* that it doesn't pollute future transactions.
*/
iip->ili_dirty_flags = 0;
return 0;
}
/*
* The logged size of an inode fork is always the current size of the inode
* fork. This means that when an inode fork is relogged, the size of the logged
@@ -662,6 +809,8 @@ xfs_inode_item_committing(
}
static const struct xfs_item_ops xfs_inode_item_ops = {
.iop_sort = xfs_inode_item_sort,
.iop_precommit = xfs_inode_item_precommit,
.iop_size = xfs_inode_item_size,
.iop_format = xfs_inode_item_format,
.iop_pin = xfs_inode_item_pin,

View File

@@ -17,6 +17,7 @@ struct xfs_inode_log_item {
struct xfs_log_item ili_item; /* common portion */
struct xfs_inode *ili_inode; /* inode ptr */
unsigned short ili_lock_flags; /* inode lock flags */
unsigned int ili_dirty_flags; /* dirty in current tx */
/*
* The ili_lock protects the interactions between the dirty state and
* the flush state of the inode log item. This allows us to do atomic

View File

@@ -80,6 +80,17 @@ xfs_bulkstat_one_int(
if (error)
goto out;
/* Reload the incore unlinked list to avoid failure in inodegc. */
if (xfs_inode_unlinked_incomplete(ip)) {
error = xfs_inode_reload_unlinked_bucket(tp, ip);
if (error) {
xfs_iunlock(ip, XFS_ILOCK_SHARED);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
xfs_irele(ip);
return error;
}
}
ASSERT(ip != NULL);
ASSERT(ip->i_imap.im_blkno != 0);
inode = VFS_I(ip);

View File

@@ -639,7 +639,6 @@ xfs_log_mount(
int num_bblks)
{
struct xlog *log;
bool fatal = xfs_has_crc(mp);
int error = 0;
int min_logfsbs;
@@ -661,53 +660,37 @@ xfs_log_mount(
mp->m_log = log;
/*
* Validate the given log space and drop a critical message via syslog
* if the log size is too small that would lead to some unexpected
* situations in transaction log space reservation stage.
* Now that we have set up the log and it's internal geometry
* parameters, we can validate the given log space and drop a critical
* message via syslog if the log size is too small. A log that is too
* small can lead to unexpected situations in transaction log space
* reservation stage. The superblock verifier has already validated all
* the other log geometry constraints, so we don't have to check those
* here.
*
* Note: we can't just reject the mount if the validation fails. This
* would mean that people would have to downgrade their kernel just to
* remedy the situation as there is no way to grow the log (short of
* black magic surgery with xfs_db).
* Note: For v4 filesystems, we can't just reject the mount if the
* validation fails. This would mean that people would have to
* downgrade their kernel just to remedy the situation as there is no
* way to grow the log (short of black magic surgery with xfs_db).
*
* We can, however, reject mounts for CRC format filesystems, as the
* We can, however, reject mounts for V5 format filesystems, as the
* mkfs binary being used to make the filesystem should never create a
* filesystem with a log that is too small.
*/
min_logfsbs = xfs_log_calc_minimum_size(mp);
if (mp->m_sb.sb_logblocks < min_logfsbs) {
xfs_warn(mp,
"Log size %d blocks too small, minimum size is %d blocks",
mp->m_sb.sb_logblocks, min_logfsbs);
error = -EINVAL;
} else if (mp->m_sb.sb_logblocks > XFS_MAX_LOG_BLOCKS) {
xfs_warn(mp,
"Log size %d blocks too large, maximum size is %lld blocks",
mp->m_sb.sb_logblocks, XFS_MAX_LOG_BLOCKS);
error = -EINVAL;
} else if (XFS_FSB_TO_B(mp, mp->m_sb.sb_logblocks) > XFS_MAX_LOG_BYTES) {
xfs_warn(mp,
"log size %lld bytes too large, maximum size is %lld bytes",
XFS_FSB_TO_B(mp, mp->m_sb.sb_logblocks),
XFS_MAX_LOG_BYTES);
error = -EINVAL;
} else if (mp->m_sb.sb_logsunit > 1 &&
mp->m_sb.sb_logsunit % mp->m_sb.sb_blocksize) {
xfs_warn(mp,
"log stripe unit %u bytes must be a multiple of block size",
mp->m_sb.sb_logsunit);
error = -EINVAL;
fatal = true;
}
if (error) {
/*
* Log check errors are always fatal on v5; or whenever bad
* metadata leads to a crash.
*/
if (fatal) {
if (xfs_has_crc(mp)) {
xfs_crit(mp, "AAIEEE! Log failed size checks. Abort!");
ASSERT(0);
error = -EINVAL;
goto out_free_log;
}
xfs_crit(mp, "Log size out of supported range.");

View File

@@ -2711,7 +2711,9 @@ xlog_recover_iunlink_bucket(
* just to flush the inodegc queue and wait for it to
* complete.
*/
xfs_inodegc_flush(mp);
error = xfs_inodegc_flush(mp);
if (error)
break;
}
prev_agino = agino;
@@ -2719,10 +2721,15 @@ xlog_recover_iunlink_bucket(
}
if (prev_ip) {
int error2;
ip->i_prev_unlinked = prev_agino;
xfs_irele(prev_ip);
error2 = xfs_inodegc_flush(mp);
if (error2 && !error)
return error2;
}
xfs_inodegc_flush(mp);
return error;
}
@@ -2789,7 +2796,6 @@ xlog_recover_iunlink_ag(
* bucket and remaining inodes on it unreferenced and
* unfreeable.
*/
xfs_inodegc_flush(pag->pag_mount);
xlog_recover_clear_agi_bucket(pag, bucket);
}
}
@@ -2806,13 +2812,6 @@ xlog_recover_process_iunlinks(
for_each_perag(log->l_mp, agno, pag)
xlog_recover_iunlink_ag(pag);
/*
* Flush the pending unlinked inodes to ensure that the inactivations
* are fully completed on disk and the incore inodes can be reclaimed
* before we signal that recovery is complete.
*/
xfs_inodegc_flush(log->l_mp);
}
STATIC void

View File

@@ -62,6 +62,7 @@ struct xfs_error_cfg {
struct xfs_inodegc {
struct llist_head list;
struct delayed_work work;
int error;
/* approximate count of inodes in the list */
unsigned int items;
@@ -400,6 +401,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID)
#define XFS_OPSTATE_WARNED_SHRINK 8
/* Kernel has logged a warning about logged xattr updates being used. */
#define XFS_OPSTATE_WARNED_LARP 9
/* Mount time quotacheck is running */
#define XFS_OPSTATE_QUOTACHECK_RUNNING 10
#define __XFS_IS_OPSTATE(name, NAME) \
static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -422,6 +425,11 @@ __XFS_IS_OPSTATE(inode32, INODE32)
__XFS_IS_OPSTATE(readonly, READONLY)
__XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED)
__XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED)
#ifdef CONFIG_XFS_QUOTA
__XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING)
#else
# define xfs_is_quotacheck_running(mp) (false)
#endif
static inline bool
xfs_should_warn(struct xfs_mount *mp, long nr)
@@ -439,7 +447,8 @@ xfs_should_warn(struct xfs_mount *mp, long nr)
{ (1UL << XFS_OPSTATE_BLOCKGC_ENABLED), "blockgc" }, \
{ (1UL << XFS_OPSTATE_WARNED_SCRUB), "wscrub" }, \
{ (1UL << XFS_OPSTATE_WARNED_SHRINK), "wshrink" }, \
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }
{ (1UL << XFS_OPSTATE_WARNED_LARP), "wlarp" }, \
{ (1UL << XFS_OPSTATE_QUOTACHECK_RUNNING), "quotacheck" }
/*
* Max and min values for mount-option defined I/O

View File

@@ -114,7 +114,8 @@ xfs_dax_notify_ddev_failure(
int error = 0;
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, daddr);
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
xfs_fsblock_t end_fsbno = XFS_DADDR_TO_FSB(mp, daddr + bblen);
xfs_fsblock_t end_fsbno = XFS_DADDR_TO_FSB(mp,
daddr + bblen - 1);
xfs_agnumber_t end_agno = XFS_FSB_TO_AGNO(mp, end_fsbno);
error = xfs_trans_alloc_empty(mp, &tp);
@@ -125,8 +126,8 @@ xfs_dax_notify_ddev_failure(
struct xfs_rmap_irec ri_low = { };
struct xfs_rmap_irec ri_high;
struct xfs_agf *agf;
xfs_agblock_t agend;
struct xfs_perag *pag;
xfs_agblock_t range_agend;
pag = xfs_perag_get(mp, agno);
error = xfs_alloc_read_agf(pag, tp, 0, &agf_bp);
@@ -147,10 +148,10 @@ xfs_dax_notify_ddev_failure(
ri_high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsbno);
agf = agf_bp->b_addr;
agend = min(be32_to_cpu(agf->agf_length),
range_agend = min(be32_to_cpu(agf->agf_length) - 1,
ri_high.rm_startblock);
notify.startblock = ri_low.rm_startblock;
notify.blockcount = agend - ri_low.rm_startblock;
notify.blockcount = range_agend + 1 - ri_low.rm_startblock;
error = xfs_rmap_query_range(cur, &ri_low, &ri_high,
xfs_dax_failure_fn, &notify);
@@ -210,7 +211,7 @@ xfs_dax_notify_failure(
ddev_end = ddev_start + bdev_nr_bytes(mp->m_ddev_targp->bt_bdev) - 1;
/* Ignore the range out of filesystem area */
if (offset + len < ddev_start)
if (offset + len - 1 < ddev_start)
return -ENXIO;
if (offset > ddev_end)
return -ENXIO;
@@ -222,8 +223,8 @@ xfs_dax_notify_failure(
len -= ddev_start - offset;
offset = 0;
}
if (offset + len > ddev_end)
len -= ddev_end - offset;
if (offset + len - 1 > ddev_end)
len = ddev_end - offset + 1;
return xfs_dax_notify_ddev_failure(mp, BTOBB(offset), BTOBB(len),
mf_flags);

View File

@@ -422,6 +422,14 @@ xfs_qm_dquot_isolate(
if (!xfs_dqlock_nowait(dqp))
goto out_miss_busy;
/*
* If something else is freeing this dquot and hasn't yet removed it
* from the LRU, leave it for the freeing task to complete the freeing
* process rather than risk it being free from under us here.
*/
if (dqp->q_flags & XFS_DQFLAG_FREEING)
goto out_miss_unlock;
/*
* This dquot has acquired a reference in the meantime remove it from
* the freelist and try again.
@@ -441,10 +449,8 @@ xfs_qm_dquot_isolate(
* skip it so there is time for the IO to complete before we try to
* reclaim it again on the next LRU pass.
*/
if (!xfs_dqflock_nowait(dqp)) {
xfs_dqunlock(dqp);
goto out_miss_busy;
}
if (!xfs_dqflock_nowait(dqp))
goto out_miss_unlock;
if (XFS_DQ_IS_DIRTY(dqp)) {
struct xfs_buf *bp = NULL;
@@ -478,6 +484,8 @@ xfs_qm_dquot_isolate(
XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaims);
return LRU_REMOVED;
out_miss_unlock:
xfs_dqunlock(dqp);
out_miss_busy:
trace_xfs_dqreclaim_busy(dqp);
XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaim_misses);
@@ -1152,6 +1160,19 @@ xfs_qm_dqusage_adjust(
if (error)
return error;
/*
* Reload the incore unlinked list to avoid failure in inodegc.
* Use an unlocked check here because unrecovered unlinked inodes
* should be somewhat rare.
*/
if (xfs_inode_unlinked_incomplete(ip)) {
error = xfs_inode_reload_unlinked(ip);
if (error) {
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
goto error0;
}
}
ASSERT(ip->i_delayed_blks == 0);
if (XFS_IS_REALTIME_INODE(ip)) {
@@ -1165,6 +1186,7 @@ xfs_qm_dqusage_adjust(
}
nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
xfs_iflags_clear(ip, XFS_IQUOTAUNCHECKED);
/*
* Add the (disk blocks and inode) resources occupied by this
@@ -1311,17 +1333,18 @@ xfs_qm_quotacheck(
flags |= XFS_PQUOTA_CHKD;
}
xfs_set_quotacheck_running(mp);
error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
NULL);
if (error) {
/*
* The inode walk may have partially populated the dquot
* caches. We must purge them before disabling quota and
* tearing down the quotainfo, or else the dquots will leak.
*/
xfs_qm_dqpurge_all(mp);
goto error_return;
}
xfs_clear_quotacheck_running(mp);
/*
* On error, the inode walk may have partially populated the dquot
* caches. We must purge them before disabling quota and tearing down
* the quotainfo, or else the dquots will leak.
*/
if (error)
goto error_purge;
/*
* We've made all the changes that we need to make incore. Flush them
@@ -1355,10 +1378,8 @@ xfs_qm_quotacheck(
* and turn quotaoff. The dquots won't be attached to any of the inodes
* at this point (because we intentionally didn't in dqget_noattach).
*/
if (error) {
xfs_qm_dqpurge_all(mp);
goto error_return;
}
if (error)
goto error_purge;
/*
* If one type of quotas is off, then it will lose its
@@ -1368,7 +1389,7 @@ xfs_qm_quotacheck(
mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD;
mp->m_qflags |= flags;
error_return:
error_return:
xfs_buf_delwri_cancel(&buffer_list);
if (error) {
@@ -1387,6 +1408,21 @@ xfs_qm_quotacheck(
} else
xfs_notice(mp, "Quotacheck: Done.");
return error;
error_purge:
/*
* On error, we may have inodes queued for inactivation. This may try
* to attach dquots to the inode before running cleanup operations on
* the inode and this can race with the xfs_qm_destroy_quotainfo() call
* below that frees mp->m_quotainfo. To avoid this race, flush all the
* pending inodegc operations before we purge the dquots from memory,
* ensuring that background inactivation is idle whilst we turn off
* quotas.
*/
xfs_inodegc_flush(mp);
xfs_qm_dqpurge_all(mp);
goto error_return;
}
/*

View File

@@ -1089,6 +1089,7 @@ xfs_inodegc_init_percpu(
#endif
init_llist_head(&gc->list);
gc->items = 0;
gc->error = 0;
INIT_DELAYED_WORK(&gc->work, xfs_inodegc_worker);
}
return 0;

View File

@@ -1877,6 +1877,7 @@ DEFINE_ALLOC_EVENT(xfs_alloc_small_notenough);
DEFINE_ALLOC_EVENT(xfs_alloc_small_done);
DEFINE_ALLOC_EVENT(xfs_alloc_small_error);
DEFINE_ALLOC_EVENT(xfs_alloc_vextent_badargs);
DEFINE_ALLOC_EVENT(xfs_alloc_vextent_skip_deadlock);
DEFINE_ALLOC_EVENT(xfs_alloc_vextent_nofix);
DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
@@ -3678,6 +3679,51 @@ TRACE_EVENT(xfs_iunlink_update_dinode,
__entry->new_ptr)
);
TRACE_EVENT(xfs_iunlink_reload_next,
TP_PROTO(struct xfs_inode *ip),
TP_ARGS(ip),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
__field(xfs_agino_t, agino)
__field(xfs_agino_t, prev_agino)
__field(xfs_agino_t, next_agino)
),
TP_fast_assign(
__entry->dev = ip->i_mount->m_super->s_dev;
__entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino);
__entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino);
__entry->prev_agino = ip->i_prev_unlinked;
__entry->next_agino = ip->i_next_unlinked;
),
TP_printk("dev %d:%d agno 0x%x agino 0x%x prev_unlinked 0x%x next_unlinked 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agino,
__entry->prev_agino,
__entry->next_agino)
);
TRACE_EVENT(xfs_inode_reload_unlinked_bucket,
TP_PROTO(struct xfs_inode *ip),
TP_ARGS(ip),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
__field(xfs_agino_t, agino)
),
TP_fast_assign(
__entry->dev = ip->i_mount->m_super->s_dev;
__entry->agno = XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino);
__entry->agino = XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino);
),
TP_printk("dev %d:%d agno 0x%x agino 0x%x bucket %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agino,
__entry->agino % XFS_AGI_UNLINKED_BUCKETS)
);
DECLARE_EVENT_CLASS(xfs_ag_inode_class,
TP_PROTO(struct xfs_inode *ip),
TP_ARGS(ip),

View File

@@ -290,7 +290,9 @@ retry:
* Do not perform a synchronous scan because callers can hold
* other locks.
*/
xfs_blockgc_flush_all(mp);
error = xfs_blockgc_flush_all(mp);
if (error)
return error;
want_retry = false;
goto retry;
}
@@ -970,6 +972,11 @@ __xfs_trans_commit(
error = xfs_defer_finish_noroll(&tp);
if (error)
goto out_unreserve;
/* Run precommits from final tx in defer chain. */
error = xfs_trans_run_precommits(tp);
if (error)
goto out_unreserve;
}
/*

View File

@@ -296,9 +296,22 @@ struct nft_set_elem {
void *priv;
};
/**
* enum nft_iter_type - nftables set iterator type
*
* @NFT_ITER_READ: read-only iteration over set elements
* @NFT_ITER_UPDATE: iteration under mutex to update set element state
*/
enum nft_iter_type {
NFT_ITER_UNSPEC,
NFT_ITER_READ,
NFT_ITER_UPDATE,
};
struct nft_set;
struct nft_set_iter {
u8 genmask;
enum nft_iter_type type:8;
unsigned int count;
unsigned int skip;
int err;

View File

@@ -5196,8 +5196,10 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
if (beacon->tail)
skb_put_data(skb, beacon->tail, beacon->tail_len);
if (ieee80211_beacon_protect(skb, local, sdata, link) < 0)
if (ieee80211_beacon_protect(skb, local, sdata, link) < 0) {
dev_kfree_skb(skb);
return NULL;
}
ieee80211_beacon_get_finish(hw, vif, link, offs, beacon, skb,
chanctx_conf, csa_off_base);

View File

@@ -628,6 +628,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
{
struct nft_set_iter iter = {
.genmask = nft_genmask_next(ctx->net),
.type = NFT_ITER_UPDATE,
.fn = nft_mapelem_deactivate,
};
@@ -5143,6 +5144,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
}
iter.genmask = nft_genmask_next(ctx->net);
iter.type = NFT_ITER_UPDATE;
iter.skip = 0;
iter.count = 0;
iter.err = 0;
@@ -5218,6 +5220,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
{
struct nft_set_iter iter = {
.genmask = nft_genmask_next(ctx->net),
.type = NFT_ITER_UPDATE,
.fn = nft_mapelem_activate,
};
@@ -5574,6 +5577,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
args.cb = cb;
args.skb = skb;
args.iter.genmask = nft_genmask_cur(net);
args.iter.type = NFT_ITER_READ;
args.iter.skip = cb->args[0];
args.iter.count = 0;
args.iter.err = 0;
@@ -6957,6 +6961,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
{
struct nft_set_iter iter = {
.genmask = genmask,
.type = NFT_ITER_UPDATE,
.fn = nft_setelem_flush,
};

View File

@@ -211,6 +211,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
return 0;
iter.genmask = nft_genmask_next(ctx->net);
iter.type = NFT_ITER_UPDATE;
iter.skip = 0;
iter.count = 0;
iter.err = 0;

View File

@@ -2042,13 +2042,15 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_iter *iter)
{
struct nft_pipapo *priv = nft_set_priv(set);
struct net *net = read_pnet(&set->net);
const struct nft_pipapo_match *m;
const struct nft_pipapo_field *f;
int i, r;
WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
iter->type != NFT_ITER_UPDATE);
rcu_read_lock();
if (iter->genmask == nft_genmask_cur(net))
if (iter->type == NFT_ITER_READ)
m = rcu_dereference(priv->match);
else
m = priv->clone;

View File

@@ -9,7 +9,8 @@
struct nft_socket {
enum nft_socket_keys key:8;
u8 level;
u8 level; /* cgroupv2 level to extract */
u8 level_user; /* cgroupv2 level provided by userspace */
u8 len;
union {
u8 dreg;
@@ -53,6 +54,28 @@ nft_sock_get_eval_cgroupv2(u32 *dest, struct sock *sk, const struct nft_pktinfo
memcpy(dest, &cgid, sizeof(u64));
return true;
}
/* process context only, uses current->nsproxy. */
static noinline int nft_socket_cgroup_subtree_level(void)
{
struct cgroup *cgrp = cgroup_get_from_path("/");
int level;
if (IS_ERR(cgrp))
return PTR_ERR(cgrp);
level = cgrp->level;
cgroup_put(cgrp);
if (WARN_ON_ONCE(level > 255))
return -ERANGE;
if (WARN_ON_ONCE(level < 0))
return -EINVAL;
return level;
}
#endif
static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt)
@@ -174,9 +197,10 @@ static int nft_socket_init(const struct nft_ctx *ctx,
case NFT_SOCKET_MARK:
len = sizeof(u32);
break;
#ifdef CONFIG_CGROUPS
#ifdef CONFIG_SOCK_CGROUP_DATA
case NFT_SOCKET_CGROUPV2: {
unsigned int level;
int err;
if (!tb[NFTA_SOCKET_LEVEL])
return -EINVAL;
@@ -185,6 +209,17 @@ static int nft_socket_init(const struct nft_ctx *ctx,
if (level > 255)
return -EOPNOTSUPP;
err = nft_socket_cgroup_subtree_level();
if (err < 0)
return err;
priv->level_user = level;
level += err;
/* Implies a giant cgroup tree */
if (WARN_ON_ONCE(level > 255))
return -EOPNOTSUPP;
priv->level = level;
len = sizeof(u64);
break;
@@ -209,7 +244,7 @@ static int nft_socket_dump(struct sk_buff *skb,
if (nft_dump_register(skb, NFTA_SOCKET_DREG, priv->dreg))
return -1;
if (priv->key == NFT_SOCKET_CGROUPV2 &&
nla_put_be32(skb, NFTA_SOCKET_LEVEL, htonl(priv->level)))
nla_put_be32(skb, NFTA_SOCKET_LEVEL, htonl(priv->level_user)))
return -1;
return 0;
}

View File

@@ -228,7 +228,6 @@ void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,
static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev)
{
lockdep_assert_held(&wdev->wiphy->mtx);
mutex_lock(&wdev->mtx);
__acquire(wdev->mtx);
}
@@ -236,16 +235,11 @@ static inline void wdev_lock(struct wireless_dev *wdev)
static inline void wdev_unlock(struct wireless_dev *wdev)
__releases(wdev)
{
lockdep_assert_held(&wdev->wiphy->mtx);
__release(wdev->mtx);
mutex_unlock(&wdev->mtx);
}
static inline void ASSERT_WDEV_LOCK(struct wireless_dev *wdev)
{
lockdep_assert_held(&wdev->wiphy->mtx);
lockdep_assert_held(&wdev->mtx);
}
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
{

View File

@@ -4928,6 +4928,30 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
}
}
static void alc_hp_mute_disable(struct hda_codec *codec, unsigned int delay)
{
if (delay <= 0)
delay = 75;
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
msleep(delay);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
msleep(delay);
}
static void alc_hp_enable_unmute(struct hda_codec *codec, unsigned int delay)
{
if (delay <= 0)
delay = 75;
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
msleep(delay);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
msleep(delay);
}
static const struct coef_fw alc225_pre_hsmode[] = {
UPDATE_COEF(0x4a, 1<<8, 0),
UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
@@ -5029,6 +5053,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
case 0x10ec0236:
case 0x10ec0256:
case 0x19e58326:
alc_hp_mute_disable(codec, 75);
alc_process_coef_fw(codec, coef0256);
break;
case 0x10ec0234:
@@ -5063,6 +5088,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
case 0x10ec0295:
case 0x10ec0289:
case 0x10ec0299:
alc_hp_mute_disable(codec, 75);
alc_process_coef_fw(codec, alc225_pre_hsmode);
alc_process_coef_fw(codec, coef0225);
break;
@@ -5288,6 +5314,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
case 0x10ec0299:
alc_process_coef_fw(codec, alc225_pre_hsmode);
alc_process_coef_fw(codec, coef0225);
alc_hp_enable_unmute(codec, 75);
break;
case 0x10ec0255:
alc_process_coef_fw(codec, coef0255);
@@ -5300,6 +5327,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
alc_write_coef_idx(codec, 0x45, 0xc089);
msleep(50);
alc_process_coef_fw(codec, coef0256);
alc_hp_enable_unmute(codec, 75);
break;
case 0x10ec0234:
case 0x10ec0274:
@@ -5397,6 +5425,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
case 0x10ec0256:
case 0x19e58326:
alc_process_coef_fw(codec, coef0256);
alc_hp_enable_unmute(codec, 75);
break;
case 0x10ec0234:
case 0x10ec0274:
@@ -5445,6 +5474,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
alc_process_coef_fw(codec, coef0225_2);
else
alc_process_coef_fw(codec, coef0225_1);
alc_hp_enable_unmute(codec, 75);
break;
case 0x10ec0867:
alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
@@ -5512,6 +5542,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
case 0x10ec0256:
case 0x19e58326:
alc_process_coef_fw(codec, coef0256);
alc_hp_enable_unmute(codec, 75);
break;
case 0x10ec0234:
case 0x10ec0274:
@@ -5549,6 +5580,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
case 0x10ec0289:
case 0x10ec0299:
alc_process_coef_fw(codec, coef0225);
alc_hp_enable_unmute(codec, 75);
break;
}
codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
@@ -5617,25 +5649,21 @@ static void alc_determine_headset_type(struct hda_codec *codec)
alc_write_coef_idx(codec, 0x06, 0x6104);
alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
msleep(80);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
alc_process_coef_fw(codec, coef0255);
msleep(300);
val = alc_read_coef_idx(codec, 0x46);
is_ctia = (val & 0x0070) == 0x0070;
if (!is_ctia) {
alc_write_coef_idx(codec, 0x45, 0xe089);
msleep(100);
val = alc_read_coef_idx(codec, 0x46);
if ((val & 0x0070) == 0x0070)
is_ctia = false;
else
is_ctia = true;
}
alc_write_coefex_idx(codec, 0x57, 0x3, 0x0da3);
alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
msleep(80);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
break;
case 0x10ec0234:
case 0x10ec0274:
@@ -5712,12 +5740,6 @@ static void alc_determine_headset_type(struct hda_codec *codec)
case 0x10ec0295:
case 0x10ec0289:
case 0x10ec0299:
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
msleep(80);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
alc_process_coef_fw(codec, alc225_pre_hsmode);
alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000);
val = alc_read_coef_idx(codec, 0x45);
@@ -5734,15 +5756,19 @@ static void alc_determine_headset_type(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0x46);
is_ctia = (val & 0x00f0) == 0x00f0;
}
if (!is_ctia) {
alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x38<<10);
alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
msleep(100);
val = alc_read_coef_idx(codec, 0x46);
if ((val & 0x00f0) == 0x00f0)
is_ctia = false;
else
is_ctia = true;
}
alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6);
alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4);
alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
msleep(80);
snd_hda_codec_write(codec, 0x21, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
break;
case 0x10ec0867:
is_ctia = true;

View File

@@ -152,6 +152,8 @@ static const struct platform_device_id board_ids[] = {
},
{ }
};
MODULE_DEVICE_TABLE(platform, board_ids);
static struct platform_driver acp_asoc_audio = {
.driver = {
.name = "sof_mach",

View File

@@ -44,6 +44,7 @@ static const struct platform_device_id db1200_pids[] = {
},
{},
};
MODULE_DEVICE_TABLE(platform, db1200_pids);
/*------------------------- AC97 PART ---------------------------*/

View File

@@ -623,6 +623,7 @@ static const struct of_device_id tda7419_of_match[] = {
{ .compatible = "st,tda7419" },
{ },
};
MODULE_DEVICE_TABLE(of, tda7419_of_match);
static struct i2c_driver tda7419_driver = {
.driver = {

View File

@@ -84,7 +84,6 @@ static const struct dmi_system_id lenovo_yoga_tab3_x90[] = {
/* Lenovo Yoga Tab 3 Pro YT3-X90, codec missing from DSDT */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
},
},

View File

@@ -817,6 +817,7 @@ static const struct of_device_id kmb_plat_of_match[] = {
{ .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai},
{}
};
MODULE_DEVICE_TABLE(of, kmb_plat_of_match);
static int kmb_plat_dai_probe(struct platform_device *pdev)
{

View File

@@ -663,6 +663,9 @@ static struct snd_sof_of_mach sof_mt8195_machs[] = {
{
.compatible = "google,tomato",
.sof_tplg_filename = "sof-mt8195-mt6359-rt1019-rt5682.tplg"
}, {
.compatible = "google,dojo",
.sof_tplg_filename = "sof-mt8195-mt6359-max98390-rt5682.tplg"
}, {
.compatible = "mediatek,mt8195",
.sof_tplg_filename = "sof-mt8195.tplg"

View File

@@ -47,7 +47,7 @@ $(OUTPUT)hv_fcopy_daemon: $(HV_FCOPY_DAEMON_IN)
clean:
rm -f $(ALL_PROGRAMS)
find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete -o -name '\.*.cmd' -delete
install: $(ALL_PROGRAMS)
install -d -m 755 $(DESTDIR)$(sbindir); \

View File

@@ -3048,7 +3048,9 @@ fullmesh_tests()
pm_nl_set_limits $ns1 1 3
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,fullmesh
if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,fullmesh
fi
run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow
chk_join_nr 3 3 3
chk_add_nr 1 1