Linux 4.4.223
* mac80211: add ieee80211_is_any_nullfunc()
include/linux/ieee80211.h
ALSA: hda: Match both PCI ID and SSID for driver blacklist
sctp: Fix SHUTDOWN CTSN Ack in the peer restart case
macvlan: Fix potential use-after free for broadcasts
net: ep93xx_eth: Do not crash unloading module
* net: skbuff: Remove errornous length validation in skb_vlan_pop()
net/core/skbuff.c
bna: add missing per queue ethtool stat
* bridge: Fix problems around fdb entries pointing to the bridge device
net/bridge/br_fdb.c
brcmfmac: restore stopping netdev queue when bus clogs up
brcmfmac: add fallback for devices that do not report per-chain values
pinctrl: tegra: Correctly check the supported configuration
ata: sata_dwc_460ex: remove incorrect locking
net: ethernet: davinci_emac: Fix platform_data overwrite
cxl: Fix DAR check & use REGION_ID instead of opencoding
at803x: fix reset handling
net: dsa: mv88e6xxx: fix port VLAN maps
* regulator: core: Rely on regulator_dev_release to free constraints
drivers/regulator/core.c
net: mv643xx_eth: fix packet corruption with TSO and tiny unaligned packets.
ovs/vxlan: fix rtnl notifications on iface deletion
net: ethoc: Fix early error paths
net: vxlan: lwt: Fix vxlan local traffic.
mvpp2: use correct size for memset
ravb: Add missing free_irq() call to ravb_close()
net: macb: replace macb_writel() call by queue_writel() to update queue ISR
net: mvneta: fix trivial cut-off issue in mvneta_ethtool_update_stats
* net: icmp_route_lookup should use rt dev to determine L3 domain
net/ipv4/icmp.c
hwrng: exynos - Disable runtime PM on driver unbind
* l2tp: fix use-after-free during module unload
net/l2tp/l2tp_core.c
net: ehea: avoid null pointer dereference
net: dsa: mv88e6xxx: enable SA learning on DSA ports
* net: bridge: don't increment tx_dropped in br_do_proxy_arp
net/bridge/br_input.c
net: hns: fix device reference leaks
net: ethernet: ti: cpsw: fix secondary-emac probe error path
net: ethernet: ti: cpsw: fix device and of_node leaks
net: ethernet: mvneta: Remove IFF_UNICAST_FLT which is not implemented
net: ethernet: davinci_emac: Fix devioctl while in fixed link
bnxt_en: Remove locking around txr->dev_state
net: axienet: Fix return value check in axienet_probe()
* qdisc: fix a module refcount leak in qdisc_create_dflt()
net/sched/sch_generic.c
bnxt: add a missing rcu synchronization
ovs/geneve: fix rtnl notifications on iface deletion
net: ethernet: stmmac: dwmac-generic: fix probe error path
fq_codel: return non zero qlen in class dumps
net: ethernet: stmmac: dwmac-rk: fix probe error path
* rtnl: reset calcit fptr in rtnl_unregister()
net/core/rtnetlink.c
net: ethernet: stmmac: dwmac-sti: fix probe error path
et131x: Fix logical vs bitwise check in et131x_tx_timeout()
* net: icmp6_send should use dst dev to determine L3 domain
net/ipv6/icmp.c
tipc: fix the error handling in tipc_udp_enable()
macvtap: segmented packet is consumed
net: macb: add missing free_netdev() on error in macb_probe()
cxgbi: fix uninitialized flowi6
net: bcmsysport: Device stats are unsigned long
sfc: clear napi_hash state when copying channels
sfc: fix potential stack corruption from running past stat bitmask
gre: reject GUE and FOU in collect metadata mode
gre: build header correctly for collect metadata tunnels
gre: do not assign header_ops in collect metadata mode
ovs/gre: fix rtnl notifications on iface deletion
net: bcmgenet: device stats are unsigned long
net: bcmgenet: fix skb_len in bcmgenet_xmit_single()
cxgb4/cxgb4vf: Fixes regression in perf when tx vlan offload is disabled
openvswitch: update checksum in {push,pop}_mpls
dmaengine: edma: Add probe callback to edma_tptc_driver
* dm: fix second blk_delay_queue() parameter to be in msec units not jiffies
drivers/md/dm.c
* blk-mq: fix undefined behaviour in order_to_size()
block/blk-mq.c
gfs2: fix flock panic issue
net: dsa: mv88e6xxx: unlock DSA and CPU ports
* Revert "cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT"
drivers/cpufreq/cpufreq.c
include/linux/cpufreq.h
MIPS: perf: Remove incorrect odd/even counter handling for I6400
* bonding: fix length of actor system
drivers/net/bonding/bond_netlink.c
ALSA: fm801: Initialize chip after IRQ handler is registered
xprtrdma: Fix backchannel allocation of extra rpcrdma_reps
mlx4: do not call napi_schedule() without care
* ipv4: Fix table id reference in fib_sync_down_addr
net/ipv4/fib_semantics.c
* vti6: fix input path
include/net/xfrm.h
net/ipv6/ip6_vti.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_tunnel.c
* net: Don't delete routes in different VRFs
include/net/ip_fib.h
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
* net: vrf: Fix dst reference counting
include/net/ip6_route.h
include/net/route.h
net/ipv4/route.c
net/ipv6/route.c
power_supply: tps65217-charger: Fix NULL deref during property export
power: bq27xxx_battery: Fix bq27541 AveragePower register address
power: test_power: correctly handle empty writes
power: bq27xxx: fix register numbers of bq27500
power: bq27xxx: fix reading for bq27000 and bq27010
* sched/preempt: Fix preempt_count manipulations
include/asm-generic/preempt.h
pkt_sched: fq: use proper locking in fq_dump_stats()
net_sched: flower: Avoid dissection of unmasked keys
* sched/fair: Fix calc_cfs_shares() fixed point arithmetics width confusion
kernel/sched/fair.c
mlxsw: switchx2: Fix ethernet port initialization
mlxsw: switchx2: Fix misuse of hard_header_len
net/mlx4_core: Fix QUERY FUNC CAP flags
net/mlx4: Fix uninitialized fields in rule when adding promiscuous mode to device managed flow steering
net/mlx4_en: Fix potential deadlock in port statistics flow
net/mlx4_core: Do not access comm channel if it has not yet been initialized
net/mlx4_en: Process all completions in RX rings after port goes up
net/mlx4_core: Fix the resource-type enum in res tracker to conform to FW spec
net/mlx4_core: Check device state before unregistering it
net/mlx4_en: Fix the return value of a failure in VLAN VID add/kill
net/mlx4_core: Fix access to uninitialized index
net/mlx4_core: Fix potential corruption in counters database
bpf: fix map not being uncharged during map creation failure
bpf, trace: check event type in bpf_perf_event_read
arm64: bpf: jit JMP_JSET_{X,K}
cls_bpf: reset class and reuse major in da
clk: xgene: Don't call __pa on ioremaped address
clk: imx: clk-pllv3: fix incorrect handle of enet powerdown bit
clk: multiplier: Prevent the multiplier from under / over flowing
clk: ti: omap3+: dpll: use non-locking version of clk_get_rate
clk: gpio: handle error codes for of_clk_get_parent_count()
clk: st: avoid uninitialized variable use
* udp: restore UDPlite many-cast delivery
net/ipv4/udp.c
net/ipv6/udp.c
netfilter: nft_dup: do not use sreg_dev if the user doesn't specify it
netfilter: nf_tables: destroy the set if fail to add transaction
netfilter: nft_dynset: fix panic if NFT_SET_HASH is not enabled
netfilter: nf_tables: fix a wrong check to skip the inactive rules
* net: ipv6: Fix processing of RAs in presence of VRF
include/net/ip6_fib.h
net/ipv6/route.c
* ipv6: add missing netconf notif when 'all' is updated
net/ipv6/addrconf.c
* ipv6: do not abuse GFP_ATOMIC in inet6_netconf_notify_devconf()
net/ipv6/addrconf.c
* ipv6: fix checksum annotation in udp6_csum_init
net/ipv6/ip6_checksum.c
* net: vrf: Fix dev refcnt leak due to IPv6 prefix route
net/ipv6/addrconf.c
* ipv4: accept u8 in IP_TOS ancillary data
net/ipv4/ip_sockglue.c
* ipv4: do not abuse GFP_ATOMIC in inet_netconf_notify_devconf()
net/ipv4/devinet.c
* ipv4: fix checksum annotation in udp4_csum_init
net/ipv4/udp.c
* flow_dissector: Check for IP fragmentation even if not using IPv4 address
net/core/flow_dissector.c
* ipv4: Fix memory leak in exception case for splitting tries
net/ipv4/fib_trie.c
be2net: Don't leak iomapped memory on removal.
pinctrl: bcm2835: Fix memory leak in error path
memory/tegra: Add number of TLB lines for Tegra124
target: Fix a memory leak in target_dev_lba_map_store()
qlcnic: use the correct ring in qlcnic_83xx_process_rcv_ring_diag()
qlcnic: potential NULL dereference in qlcnic_83xx_get_minidump_template()
qede: uninitialized variable in qede_start_xmit()
i40e: fix an uninitialized variable bug
power: ipaq-micro-battery: freeing the wrong variable
ethernet: micrel: fix some error codes
mfd: lp8788-irq: Uninitialized variable in irq handler
net: moxa: fix an error code
VFIO: platform: reset: fix a warning message condition
ath9k_htc: check for underflow in ath9k_htc_rx_msg()
cx23885: uninitialized variable in cx23885_av_work_handler()
am437x-vpfe: fix an uninitialized variable bug
lirc_imon: do not leave imon_probe() with mutex held
rc: allow rc modules to be loaded if rc-main is not a module
net: systemport: suppress warnings on failed Rx SKB allocations
net: bcmgenet: suppress warnings on failed Rx SKB allocations
* lib/mpi: Fix building for powerpc with clang
lib/mpi/longlong.h
scripts/config: allow colons in option strings for sed
cifs: protect updating server->dstaddr with a spinlock
wimax/i2400m: Fix potential urb refcnt leak
selftests/ipc: Fix test failure seen after initial test run
iio:ad7797: Use correct attribute_group
mdio-sun4i: oops in error handling in probe
iommu/dma: Respect IOMMU aperture when allocating
drivers: net: cpsw: don't ignore phy-mode if phy-handle is used
net: dsa: slave: fix of-node leak and phy priority
phy: micrel: Fix finding PHY properties in MAC node for KSZ9031.
* of_mdio: fix node leak in of_phy_register_fixed_link error path
drivers/of/of_mdio.c
net: phy: bcm7xxx: Fix shadow mode 2 disabling
* net: phy: Fix phy_mac_interrupt()
drivers/net/phy/phy.c
* net: phy: Avoid polling PHY with PHY_IGNORE_INTERRUPTS
drivers/net/phy/phy.c
NFC: nci: memory leak in nci_core_conn_create()
* sunrpc: Update RPCBIND_MAXNETIDLEN
include/linux/sunrpc/msg_prot.h
sctp: fix the transports round robin issue when init is retransmitted
powerpc/book3s: Fix MCE console messages for unrecoverable MCE.
powerpc/tm: Fix stack pointer corruption in __tm_recheckpoint()
perf tools: Fix perf regs mask generation
mmc: sdhci: Fix regression setting power on Trats2 board
mmc: moxart: fix wait_for_completion_interruptible_timeout return variable type
mmc: dw_mmc: rockchip: Set the drive phase properly
clk: rockchip: Revert "clk: rockchip: reset init state before mmc card initialization"
mmc: block: return error on failed mmc_blk_get()
mmc: debugfs: correct wrong voltage value
mmc: sd: limit SD card power limit according to cards capabilities
mmc: sdhci: restore behavior when setting VDD via external regulator
* Revert "ACPI / LPSS: allow to use specific PM domain during ->probe()"
drivers/acpi/acpi_lpss.c
ASoC: fsl_ssi: mark SACNT register volatile
ASoC: tegra_alc5632: check return value
ASoC: Intel: pass correct parameter in sst_alloc_stream_mrfld()
mtd: nand: denali: add missing nand_release() call in denali_remove()
* net: get rid of an signed integer overflow in ip_idents_reserve()
net/ipv4/route.c
NFS: Fix an LOCK/OPEN race when unlinking an open file
mac80211: Fix BW upgrade for TDLS peers
mac80211: TDLS: change BW calculation for WIDER_BW peers
mac80211: TDLS: always downgrade invalid chandefs
mac80211: fix mgmt-tx abort cookie and leak
* xfrm: Fix memory leak of aead algorithm name
net/xfrm/xfrm_state.c
* xfrm_user: propagate sec ctx allocation errors
net/xfrm/xfrm_user.c
* net/xfrm_input: fix possible NULL deref of tunnel.ip6->parms.i_key
net/ipv6/xfrm6_input.c
net/xfrm/xfrm_input.c
Input: edt-ft5x06 - fix setting gain, offset, and threshold via device tree
* Input: gpio-keys - fix check for disabling unsupported keys
drivers/input/keyboard/gpio_keys.c
Btrfs: clean up an error code in btrfs_init_space_info()
isa: Call isa_bus_init before dependent ISA bus drivers register
Drivers: hv: utils: use memdup_user in hvt_op_write
serial: samsung: Fix possible out of bounds access on non-DT platform
* tty: serial: msm: Support more bauds
drivers/tty/serial/msm_serial.c
batman-adv: replace WARN with rate limited output on non-existing VLAN
batman-adv: Fix lockdep annotation of batadv_tlv_container_remove
* net: ipv6: tcp reset, icmp need to consider L3 domain
net/ipv6/icmp.c
net/ipv6/tcp_ipv6.c
RDS:TCP: Synchronize rds_tcp_accept_one with rds_send_xmit when resetting t_sock
* tcp: do not set rtt_min to 1
net/ipv4/tcp_input.c
* net: tcp_memcontrol: properly detect ancestor socket pressure
include/net/sock.h
mlxsw: spectrum: Fix misuse of hard_header_len
mlxsw: spectrum: Indicate support for autonegotiation
mlxsw: spectrum: Don't count internal TX header bytes to stats
mlxsw: spectrum: Disable learning according to STP state
mlxsw: spectrum: Don't forward packets when STP state is DISABLED
RDMA/cxgb3: device driver frees DMA memory with different size
xprtrdma: rpcrdma_bc_receive_call() should init rq_private_buf.len
xprtrdma: xprt_rdma_free() must not release backchannel reqs
xprtrdma: Fix additional uses of spin_lock_irqsave(rb_lock)
xprtrdma: checking for NULL instead of IS_ERR()
ath10k: free cached fw bin contents when get board id fails
mtd: nand: fix ONFI parameter page layout
* bonding: prevent out of bound accesses
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_alb.c
include/net/bonding.h
* phy: fix device reference leaks
drivers/net/phy/phy_device.c
irda: Free skb on irda_accept error path.
btrfs: cleaner_kthread() doesn't need explicit freeze
sch_tbf: update backlog as well
sch_sfb: keep backlog updated with qlen
sch_qfq: keep backlog updated with qlen
* sch_prio: update backlog as well
net/sched/sch_prio.c
sch_hfsc: always keep backlog updated
sch_drr: update backlog as well
* net_sched: keep backlog updated with qlen
include/net/sch_generic.h
net/sched/sch_generic.c
net/mlx5e: Copy all L2 headers into inline segment
net/mlx5: Fix pci error recovery flow
net/mlx5: Add timeout handle to commands with callback
net/mlx5: Fix potential deadlock in command mode change
net/mlx5: Fix wait_vital for VFs and remove fixed sleep
net/mlx5: Avoid calling sleeping function by the health poll thread
net/mlx5: use mlx5_buf_alloc_node instead of mlx5_buf_alloc in mlx5_wq_ll_create
net/mlx5e: Fix blue flame quota logic
net/mlx5: Fix masking of reserved bits in XRCD number
net/mlx5: Fix the size of modify QP mailbox
net/mlx5e: Fix MLX5E_100BASE_T define
IB/mlx5: Fix FW version diaplay in sysfs
net/mlx5: Make command timeout way shorter
IB/mlx5: Fix RC transport send queue overhead computation
net/mlx5: Avoid passing dma address 0 to firmware
c8sectpfe: Rework firmware loading mechanism
* firmware: actually return NULL on failed request_firmware_nowait()
drivers/base/firmware_class.c
powerpc/pci/of: Parse unassigned resources
* GRE: Disable segmentation offloads w/ CSUM and we are encapsulated via FOU
include/linux/netdevice.h
net/core/dev.c
net/ipv4/gre_offload.c
ovs/gre,geneve: fix error path when creating an iface
IB/mlx4: Initialize hop_limit when creating address handle
mlxsw: Treat local port 64 as valid
brcmfmac: add eth_type_trans back for PCIe full dongle
vfio/pci: Allow VPD short read
alpha/PCI: Call iomem_is_exclusive() for IORESOURCE_MEM, but not IORESOURCE_IO
net/mlx4_core: Implement pci_resume callback
* PCI: Supply CPU physical address (not bus address) to iomem_is_exclusive()
drivers/pci/pci-sysfs.c
mlxsw: pci: Correctly determine if descriptor queue is full
net/mlx4_core: Do not BUG_ON during reset when PCI is offline
* dccp: limit sk_filter trim to payload
include/net/sock.h
net/core/sock.c
Bluetooth: btmrvl: fix hung task warning dump
iwlwifi: set max firmware version of 7265 to 17
mwifiex: add missing check for PCIe8997 chipset
mwifiex: fix IBSS data path issue.
* xfrm: fix crash in XFRM_MSG_GETSA netlink handler
net/xfrm/xfrm_user.c
* netfilter: nfnetlink: use original skbuff when acking batches
net/netfilter/nfnetlink.c
ALSA: fm801: detect FM-only card earlier
ALSA: fm801: propagate TUNER_ONLY bit when autodetected
ALSA: fm801: explicitly free IRQ line
x86/apic/uv: Silence a shift wrapping warning
x86/LDT: Print the real LDT base address
perf/x86: Fix filter_events() bug with event mappings
ARM: OMAP2+: hwmod: fix _idle() hwmod state sanity check sequence
ARM: dts: kirkwood: add kirkwood-ds112.dtb to Makefile
ARM: dts: kirkwood: use unique machine name for ds112
ARM: dts: orion5x: fix the missing mtd flash on linkstation lswtgl
ARM: dts: orion5x: gpio pin fixes for linkstation lswtgl
ARM: dts: kirkwood: gpio-leds fixes for linkstation ls-wvl/vl
ARM: dts: kirkwood: gpio-leds fixes for linkstation ls-wxl/wsxl
ARM: dts: kirkwood: gpio pin fixes for linkstation ls-wvl/vl
ARM: dts: kirkwood: gpio pin fixes for linkstation ls-wxl/wsxl
ARM: imx: select SRC for i.MX7
ARM: dts: armadillo800eva Correct extal1 frequency to 24 MHz
mips/panic: replace smp_send_stop() with kdump friendly version in panic path
MIPS: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
MIPS: RM7000: Double locking bug in rm7k_tc_disable()
bpf, mips: fix off-by-one in ctx offset allocation
MIPS: Octeon: Off by one in octeon_irq_gpio_map()
MIPS: c-r4k: Fix protected_writeback_scache_line for EVA
MIPS: SMP: Update cpu_foreign_map on CPU disable
MIPS: KVM: Fix translation of MFC0 ErrCtl
MIPS: perf: Fix I6400 event numbers
MIPS: Fix BC1{EQ,NE}Z return offset calculation
MIPS: math-emu: Fix BC1{EQ,NE}Z emulation
MIPS: BMIPS: Adjust mips-hpt-frequency for BCM7435
MIPS: Fix HTW config on XPA kernel without LPA enabled
MIPS: BMIPS: Pretty print BMIPS5200 processor name
MIPS: BMIPS: local_r4k___flush_cache_all needs to blast S-cache
MIPS: BMIPS: Clear MIPS_CACHE_ALIASES earlier
MIPS: BMIPS: BMIPS5000 has I cache filing from D cache
MIPS: scall: Handle seccomp filters which redirect syscalls
MIPS: smp-cps: Stop printing EJTAG exceptions to UART
MIPS: BMIPS: Fix PRID_IMP_BMIPS5000 masking for BMIPS5200
MIPS: ptrace: Drop cp0_tcstatus from regoffset_table[]
MIPS: Fix macro typo
* usb: gadget: udc: core: don't starve DMA resources
drivers/usb/gadget/udc/udc-core.c
usb: gadget: pch_udc: reorder spin_[un]lock to avoid deadlock
usb: gadged: pch_udc: get rid of redundant assignments
usb: gadget: f_acm: Fix configfs attr name
staging: rtl8192u: Fix crash due to pointers being "confusing"
drm/qxl: qxl_release leak in qxl_draw_dirty_fb()
drm/qxl: qxl_release use after free
mwifiex: fix PCIe register information for 8997 chipset
Linux 4.4.222
* selinux: properly handle multiple messages in selinux_netlink_send()
security/selinux/hooks.c
* ipv6: use READ_ONCE() for inet->hdrincl as in ipv4
net/ipv6/raw.c
ASoC: imx-spdif: Fix crash on suspend
ASoC: wm8960: Fix WM8960_SYSCLK_PLL mode
exynos4-is: fix a format string bug
perf/x86: Fix uninitialized value usage
powerpc/perf: Remove PPMU_HAS_SSLOT flag for Power8
perf hists: Fix HISTC_MEM_DCACHELINE width setting
i2c: designware-pci: use IRQF_COND_SUSPEND flag
dmaengine: dmatest: Fix iteration non-stop logic
nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl
ALSA: opti9xx: shut up gcc-10 range warning
vfio/type1: Fix VA->PA translation for PFNMAP VMAs in vaddr_get_pfn()
RDMA/mlx4: Initialize ib_spec on the stack
* PM: ACPI: Output correct message on target power state
drivers/acpi/device_pm.c
ALSA: pcm: oss: Place the plugin buffer overflow checks correctly
drm/qxl: qxl_release leak in qxl_hw_surface_alloc()
* ext4: fix special inode number checks in __ext4_iget()
fs/ext4/inode.c
Linux 4.4.221
* propagate_one(): mnt_set_mountpoint() needs mount_lock
fs/pnode.c
* ext4: unsigned int compared against zero
fs/ext4/block_validity.c
* ext4: fix block validity checks for journal inodes using indirect blocks
fs/ext4/block_validity.c
* ext4: don't perform block validity checks on the journal inode
fs/ext4/extents.c
* ext4: protect journal inode's blocks using block_validity
fs/ext4/block_validity.c
fs/ext4/inode.c
* ext4: avoid declaring fs inconsistent due to invalid file handles
fs/ext4/ext4.h
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
* ext4: convert BUG_ON's to WARN_ON's in mballoc.c
fs/ext4/mballoc.c
xen/xenbus: ensure xenbus_map_ring_valloc() returns proper grant status
scsi: target: fix PR IN / READ FULL STATUS for FC
bpf, x86: Fix encoding for lower 8-bit registers in BPF_STX BPF_B
* perf/core: fix parent pid/tid in task exit events
kernel/events/core.c
net/cxgb4: Check the return from t4_query_params properly
usb: gadget: udc: bdc: Remove unnecessary NULL checks in bdc_req_complete
mtd: cfi: fix deadloop in cfi_cmdset_0002.c do_write_buffer
* fuse: fix possibly missed wake-up after abort
fs/fuse/dev.c
sctp: use right member as the param of list_for_each_entry
remoteproc: Fix wrong rvring index computation
* usb: f_fs: Clear OS Extended descriptor counts to zero in ffs_data_reset()
drivers/usb/gadget/function/f_fs.c
UAS: fix deadlock in error handling and PM flushing work
UAS: no use logging any details in case of ENODEV
staging: vt6656: Power save stop wake_up_count wrap around.
staging: vt6656: Fix drivers TBTT timing counter.
staging: comedi: Fix comedi_device refcnt leak in comedi_open
staging: comedi: dt2815: fix writing hi byte of analog output
ARM: imx: provide v7_cpu_resume() only on ARM_CPU_SUSPEND=y
* ASoC: dapm: fixup dapm kcontrol widget
sound/soc/soc-dapm.c
* audit: check the length of userspace generated audit records
kernel/audit.c
* usb-storage: Add unusual_devs entry for JMicron JMS566
drivers/usb/storage/unusual_devs.h
tty: rocket, avoid OOB access
tty: hvc: fix buffer overflow during hvc_alloc().
KVM: VMX: Enable machine check support for 32bit targets
* KVM: Check validity of resolved slot when searching memslots
include/linux/kvm_host.h
* ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices
sound/usb/format.c
* ALSA: usb-audio: Fix usb audio refcnt leak when getting spdif
sound/usb/mixer_quirks.c
ALSA: usx2y: Fix potential NULL dereference
* USB: hub: Fix handling of connect changes during sleep
drivers/usb/core/hub.c
* USB: core: Fix free-while-in-use bug in the USB S-Glibrary
drivers/usb/core/message.c
* drivers: usb: core: Minimize irq disabling in usb_sg_cancel()
drivers/usb/core/message.c
* drivers: usb: core: Don't disable irqs in usb_sg_wait() during URB submit.
drivers/usb/core/message.c
* USB: Add USB_QUIRK_DELAY_CTRL_MSG and USB_QUIRK_DELAY_INIT for Corsair K70 RGB RAPIDFIRE
drivers/usb/core/quirks.c
USB: sisusbvga: Change port variable from signed to unsigned
* fs/namespace.c: fix mountpoint reference counter race
fs/namespace.c
iio: xilinx-xadc: Fix sequencer configuration for aux channels in simultaneous mode
iio: xilinx-xadc: Fix clearing interrupt when enabling trigger
iio: xilinx-xadc: Fix ADC-B powerdown
ALSA: hda: Remove ASUS ROG Zenith from the blacklist
* xfrm: Always set XFRM_TRANSFORMED in xfrm{4,6}_output_finish
net/ipv4/xfrm4_output.c
net/ipv6/xfrm6_output.c
team: fix hang in team_mode_get()
* tcp: cache line align MAX_TCP_HEADER
include/net/tcp.h
net/x25: Fix x25_neigh refcnt leak when receiving frame
net: netrom: Fix potential nr_neigh refcnt leak in nr_add_node
macvlan: fix null dereference in macvlan_device_event()
* ipv6: fix restrict IPV6_ADDRFORM operation
net/ipv6/ipv6_sockglue.c
pwm: bcm2835: Dynamically allocate base
pwm: renesas-tpu: Fix late Runtime PM enablement
s390/cio: avoid duplicated 'ADD' uevents
ipc/util.c: sysvipc_find_ipc() should increase position index
kernel/gcov/fs.c: gcov_seq_next() should increase position index
ASoC: Intel: atom: Take the drv->lock mutex before calling sst_send_slot_map()
scsi: iscsi: Report unbind session event when the target has been removed
pwm: rcar: Fix late Runtime PM enablement
ceph: don't skip updating wanted caps when cap is stale
ceph: return ceph_mdsc_do_request() errors from __get_parent()
scsi: lpfc: Fix kasan slab-out-of-bounds error in lpfc_unreg_login
* vti4: removed duplicate log message.
net/ipv4/ip_vti.c
crypto: mxs-dcp - make symbols 'sha1_null_hash' and 'sha256_null_hash' static
* net: ipv4: avoid unused variable warning for sysctl
net/ipv4/route.c
* net: ipv4: emulate READ_ONCE() on ->hdrincl bit-field in raw_sendmsg()
net/ipv4/raw.c
ALSA: hda - Fix incorrect usage of IS_REACHABLE()
* ext4: fix extent_status fragmentation for plain files
fs/ext4/extents.c
Linux 4.4.220
x86/vdso: Fix lsl operand order
x86/microcode/intel: replace sync_core() with native_cpuid_reg(eax)
x86/CPU: Add native CPUID variants returning a single datum
mtd: phram: fix a double free issue in error path
mtd: lpddr: Fix a double free in probe()
locktorture: Print ratio of acquisitions, not failures
tty: evh_bytechan: Fix out of bounds accesses
* fbdev: potential information leak in do_fb_ioctl()
drivers/video/fbdev/core/fbmem.c
iommu/amd: Fix the configuration of GCR3 table root pointer
ext2: fix empty body warnings when -Wextra is used
NFS: Fix memory leaks in nfs_pageio_stop_mirroring()
* compiler.h: fix error in BUILD_BUG_ON() reporting
include/linux/compiler.h
* percpu_counter: fix a data race at vm_committed_as
include/linux/percpu_counter.h
* ext4: do not commit super on read-only bdev
fs/ext4/super.c
NFS: direct.c: Fix memory leak of dreq when nfs_get_lock_context fails
clk: tegra: Fix Tegra PMC clock out parents
clk: at91: usb: continue if clk_hw_round_rate() return zero
of: unittest: kmemleak in of_unittest_platform_populate()
* of: fix missing kobject init for !SYSFS && OF_DYNAMIC config
drivers/of/base.c
soc: qcom: smem: Use le32_to_cpu for comparison
rtc: pm8xxx: Fix issue in RTC write path
wil6210: rate limit wil_rx_refill error
* scsi: ufs: ufs-qcom: remove broken hci version quirk
drivers/scsi/ufs/ufs-qcom.c
wil6210: fix temperature debugfs
wil6210: increase firmware ready timeout
drm: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
video: fbdev: sis: Remove unnecessary parentheses and commented code
ALSA: hda: Don't release card at firmware loading error
* scsi: sg: add sg_remove_request in sg_common_write
drivers/scsi/sg.c
* tracing: Fix the race between registering 'snapshot' event trigger and triggering 'snapshot' operation
kernel/trace/trace_events_trigger.c
x86/mitigations: Clear CPU buffers on the SYSCALL fast path
kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD
dm flakey: check for null arg_name in parse_features()
* ext4: do not zeroout extents beyond i_disksize
fs/ext4/extents.c
mac80211_hwsim: Use kstrndup() in place of kasprintf()
* ALSA: usb-audio: Don't override ignore_ctl_error value from the map
sound/usb/mixer.c
ASoC: Intel: mrfld: return error codes when an error occurs
ASoC: Intel: mrfld: fix incorrect check on p->sink
* ext4: fix incorrect inodes per group in error message
fs/ext4/super.c
* ext4: fix incorrect group count in ext4_fill_super error message
fs/ext4/super.c
* jbd2: improve comments about freeing data buffers whose page mapping is NULL
fs/jbd2/commit.c
* scsi: ufs: Fix ufshcd_hold() caused scheduling while atomic
drivers/scsi/ufs/ufshcd.c
* net: ipv6: do not consider routes via gateways for anycast address check
include/net/ip6_route.h
* net: ipv4: devinet: Fix crash when add/del multicast IP with autojoin
net/ipv4/devinet.c
mfd: dln2: Fix sanity checking for endpoints
misc: echo: Remove unnecessary parentheses and simplify check for zero
powerpc/fsl_booke: Avoid creating duplicate tlb1 entry
ipmi: fix hung processes in __get_guid()
drm/dp_mst: Fix clearing payload state on topology disable
Btrfs: fix crash during unmount due to race with delayed inode workers
powerpc/64/tm: Don't let userspace set regs->trap via sigreturn
libata: Return correct status in sata_pmp_eh_recover_pm() when ATA_DFLAG_DETACH is set
hfsplus: fix crash and filesystem corruption when deleting files
* kmod: make request_module() return an error when autoloading is disabled
kernel/kmod.c
Input: i8042 - add Acer Aspire 5738z to nomux list
s390/diag: fix display of diagnose call statistics
ocfs2: no need try to truncate file beyond i_size
* ext4: fix a data race at inode->i_blocks
fs/ext4/inode.c
* arm64: armv8_deprecated: Fix undef_hook mask for thumb setend
arch/arm64/kernel/armv8_deprecated.c
scsi: zfcp: fix missing erp_lock in port recovery trigger for point-to-point
IB/ipoib: Fix lockdep issue found on ipoib_ib_dev_heavy_flush
Btrfs: incremental send, fix invalid memory access
ALSA: hda: Initialize power_state field properly
xen-netfront: Rework the fix for Rx stall during OOM and network stress
* futex: futex_wake_op, do not fail on invalid op
kernel/futex.c
crypto: mxs-dcp - fix scatterlist linearization for hash
KVM: x86: Allocate new rmap and large page tracking when moving memslot
x86/entry/32: Add missing ASM_CLAC to general_protection entry
* signal: Extend exec_id to 64bits
fs/exec.c
include/linux/sched.h
kernel/signal.c
ath9k: Handle txpower changes even when TPC is disabled
MIPS: OCTEON: irq: Fix potential NULL pointer dereference
irqchip/versatile-fpga: Apply clear-mask earlier
* KEYS: reaching the keys quotas correctly
security/keys/key.c
security/keys/keyctl.c
thermal: devfreq_cooling: inline all stubs for CONFIG_DEVFREQ_THERMAL=n
acpi/x86: ignore unspecified bit positions in the ACPI global lock field
ALSA: pcm: oss: Fix regression by buffer overflow fix
ALSA: ice1724: Fix invalid access for enumerated ctl items
ALSA: hda: Fix potential access overflow in beep helper
ALSA: hda: Add driver blacklist
* ALSA: usb-audio: Add mixer workaround for TRX40 and co
sound/usb/mixer_maps.c
* usb: gadget: composite: Inform controller driver of self-powered
drivers/usb/gadget/composite.c
* usb: gadget: f_fs: Fix use after free issue as part of queue failure
drivers/usb/gadget/function/f_fs.c
ASoC: topology: use name_prefix for new kcontrol
* ASoC: dpcm: allow start or stop during pause for backend
sound/soc/soc-pcm.c
* ASoC: dapm: connect virtual mux with default value
sound/soc/soc-dapm.c
* ASoC: fix regwmask
sound/soc/soc-ops.c
misc: rtsx: set correct pcr_ops for rts522A
btrfs: track reloc roots based on their commit root bytenr
btrfs: remove a BUG_ON() from merge_reloc_roots()
locking/lockdep: Avoid recursion in lockdep_count_{for,back}ward_deps()
x86/boot: Use unsigned comparison for addresses
gfs2: Don't demote a glock until its revokes are written
libata: Remove extra scsi_host_put() in ata_scsi_add_hosts()
selftests/x86/ptrace_syscall_32: Fix no-vDSO segfault
irqchip/versatile-fpga: Handle chained IRQs properly
i2c: st: fix missing struct parameter description
qlcnic: Fix bad kzalloc null test
net: vxge: fix wrong __VA_ARGS__ usage
bus: sunxi-rsb: Return correct data when mixing 16-bit and 8-bit reads
Change-Id: Ic791260c4269d3f4db46d01098b969caed77d5e7
Signed-off-by: lucaswei <lucaswei@google.com>
627 lines
16 KiB
C
627 lines
16 KiB
C
/*
|
|
* linux/fs/pnode.c
|
|
*
|
|
* (C) Copyright IBM Corporation 2005.
|
|
* Released under GPL v2.
|
|
* Author : Ram Pai (linuxram@us.ibm.com)
|
|
*
|
|
*/
|
|
#include <linux/mnt_namespace.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/nsproxy.h>
|
|
#include "internal.h"
|
|
#include "pnode.h"
|
|
|
|
/* return the next shared peer mount of @p */
|
|
static inline struct mount *next_peer(struct mount *p)
|
|
{
|
|
return list_entry(p->mnt_share.next, struct mount, mnt_share);
|
|
}
|
|
|
|
static inline struct mount *first_slave(struct mount *p)
|
|
{
|
|
return list_entry(p->mnt_slave_list.next, struct mount, mnt_slave);
|
|
}
|
|
|
|
static inline struct mount *last_slave(struct mount *p)
|
|
{
|
|
return list_entry(p->mnt_slave_list.prev, struct mount, mnt_slave);
|
|
}
|
|
|
|
static inline struct mount *next_slave(struct mount *p)
|
|
{
|
|
return list_entry(p->mnt_slave.next, struct mount, mnt_slave);
|
|
}
|
|
|
|
static struct mount *get_peer_under_root(struct mount *mnt,
|
|
struct mnt_namespace *ns,
|
|
const struct path *root)
|
|
{
|
|
struct mount *m = mnt;
|
|
|
|
do {
|
|
/* Check the namespace first for optimization */
|
|
if (m->mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root))
|
|
return m;
|
|
|
|
m = next_peer(m);
|
|
} while (m != mnt);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Get ID of closest dominating peer group having a representative
|
|
* under the given root.
|
|
*
|
|
* Caller must hold namespace_sem
|
|
*/
|
|
int get_dominating_id(struct mount *mnt, const struct path *root)
|
|
{
|
|
struct mount *m;
|
|
|
|
for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) {
|
|
struct mount *d = get_peer_under_root(m, mnt->mnt_ns, root);
|
|
if (d)
|
|
return d->mnt_group_id;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_make_slave(struct mount *mnt)
|
|
{
|
|
struct mount *peer_mnt = mnt, *master = mnt->mnt_master;
|
|
struct mount *slave_mnt;
|
|
|
|
/*
|
|
* slave 'mnt' to a peer mount that has the
|
|
* same root dentry. If none is available then
|
|
* slave it to anything that is available.
|
|
*/
|
|
while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
|
|
peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ;
|
|
|
|
if (peer_mnt == mnt) {
|
|
peer_mnt = next_peer(mnt);
|
|
if (peer_mnt == mnt)
|
|
peer_mnt = NULL;
|
|
}
|
|
if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) &&
|
|
list_empty(&mnt->mnt_share))
|
|
mnt_release_group_id(mnt);
|
|
|
|
list_del_init(&mnt->mnt_share);
|
|
mnt->mnt_group_id = 0;
|
|
|
|
if (peer_mnt)
|
|
master = peer_mnt;
|
|
|
|
if (master) {
|
|
list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
|
|
slave_mnt->mnt_master = master;
|
|
list_move(&mnt->mnt_slave, &master->mnt_slave_list);
|
|
list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
|
|
INIT_LIST_HEAD(&mnt->mnt_slave_list);
|
|
} else {
|
|
struct list_head *p = &mnt->mnt_slave_list;
|
|
while (!list_empty(p)) {
|
|
slave_mnt = list_first_entry(p,
|
|
struct mount, mnt_slave);
|
|
list_del_init(&slave_mnt->mnt_slave);
|
|
slave_mnt->mnt_master = NULL;
|
|
}
|
|
}
|
|
mnt->mnt_master = master;
|
|
CLEAR_MNT_SHARED(mnt);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* vfsmount lock must be held for write
|
|
*/
|
|
void change_mnt_propagation(struct mount *mnt, int type)
|
|
{
|
|
if (type == MS_SHARED) {
|
|
set_mnt_shared(mnt);
|
|
return;
|
|
}
|
|
do_make_slave(mnt);
|
|
if (type != MS_SLAVE) {
|
|
list_del_init(&mnt->mnt_slave);
|
|
mnt->mnt_master = NULL;
|
|
if (type == MS_UNBINDABLE)
|
|
mnt->mnt.mnt_flags |= MNT_UNBINDABLE;
|
|
else
|
|
mnt->mnt.mnt_flags &= ~MNT_UNBINDABLE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get the next mount in the propagation tree.
|
|
* @m: the mount seen last
|
|
* @origin: the original mount from where the tree walk initiated
|
|
*
|
|
* Note that peer groups form contiguous segments of slave lists.
|
|
* We rely on that in get_source() to be able to find out if
|
|
* vfsmount found while iterating with propagation_next() is
|
|
* a peer of one we'd found earlier.
|
|
*/
|
|
static struct mount *propagation_next(struct mount *m,
|
|
struct mount *origin)
|
|
{
|
|
/* are there any slaves of this mount? */
|
|
if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
|
|
return first_slave(m);
|
|
|
|
while (1) {
|
|
struct mount *master = m->mnt_master;
|
|
|
|
if (master == origin->mnt_master) {
|
|
struct mount *next = next_peer(m);
|
|
return (next == origin) ? NULL : next;
|
|
} else if (m->mnt_slave.next != &master->mnt_slave_list)
|
|
return next_slave(m);
|
|
|
|
/* back at master */
|
|
m = master;
|
|
}
|
|
}
|
|
|
|
static struct mount *skip_propagation_subtree(struct mount *m,
|
|
struct mount *origin)
|
|
{
|
|
/*
|
|
* Advance m such that propagation_next will not return
|
|
* the slaves of m.
|
|
*/
|
|
if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
|
|
m = last_slave(m);
|
|
|
|
return m;
|
|
}
|
|
|
|
static struct mount *next_group(struct mount *m, struct mount *origin)
|
|
{
|
|
while (1) {
|
|
while (1) {
|
|
struct mount *next;
|
|
if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list))
|
|
return first_slave(m);
|
|
next = next_peer(m);
|
|
if (m->mnt_group_id == origin->mnt_group_id) {
|
|
if (next == origin)
|
|
return NULL;
|
|
} else if (m->mnt_slave.next != &next->mnt_slave)
|
|
break;
|
|
m = next;
|
|
}
|
|
/* m is the last peer */
|
|
while (1) {
|
|
struct mount *master = m->mnt_master;
|
|
if (m->mnt_slave.next != &master->mnt_slave_list)
|
|
return next_slave(m);
|
|
m = next_peer(master);
|
|
if (master->mnt_group_id == origin->mnt_group_id)
|
|
break;
|
|
if (master->mnt_slave.next == &m->mnt_slave)
|
|
break;
|
|
m = master;
|
|
}
|
|
if (m == origin)
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* all accesses are serialized by namespace_sem */
|
|
static struct user_namespace *user_ns;
|
|
static struct mount *last_dest, *first_source, *last_source, *dest_master;
|
|
static struct mountpoint *mp;
|
|
static struct hlist_head *list;
|
|
|
|
static inline bool peers(struct mount *m1, struct mount *m2)
|
|
{
|
|
return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
|
|
}
|
|
|
|
static int propagate_one(struct mount *m)
|
|
{
|
|
struct mount *child;
|
|
int type;
|
|
/* skip ones added by this propagate_mnt() */
|
|
if (IS_MNT_NEW(m))
|
|
return 0;
|
|
/* skip if mountpoint isn't covered by it */
|
|
if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
|
|
return 0;
|
|
if (peers(m, last_dest)) {
|
|
type = CL_MAKE_SHARED;
|
|
} else {
|
|
struct mount *n, *p;
|
|
bool done;
|
|
for (n = m; ; n = p) {
|
|
p = n->mnt_master;
|
|
if (p == dest_master || IS_MNT_MARKED(p))
|
|
break;
|
|
}
|
|
do {
|
|
struct mount *parent = last_source->mnt_parent;
|
|
if (last_source == first_source)
|
|
break;
|
|
done = parent->mnt_master == p;
|
|
if (done && peers(n, parent))
|
|
break;
|
|
last_source = last_source->mnt_master;
|
|
} while (!done);
|
|
|
|
type = CL_SLAVE;
|
|
/* beginning of peer group among the slaves? */
|
|
if (IS_MNT_SHARED(m))
|
|
type |= CL_MAKE_SHARED;
|
|
}
|
|
|
|
/* Notice when we are propagating across user namespaces */
|
|
if (m->mnt_ns->user_ns != user_ns)
|
|
type |= CL_UNPRIVILEGED;
|
|
child = copy_tree(last_source, last_source->mnt.mnt_root, type);
|
|
if (IS_ERR(child))
|
|
return PTR_ERR(child);
|
|
child->mnt.mnt_flags &= ~MNT_LOCKED;
|
|
read_seqlock_excl(&mount_lock);
|
|
mnt_set_mountpoint(m, mp, child);
|
|
if (m->mnt_master != dest_master)
|
|
SET_MNT_MARK(m->mnt_master);
|
|
read_sequnlock_excl(&mount_lock);
|
|
last_dest = m;
|
|
last_source = child;
|
|
hlist_add_head(&child->mnt_hash, list);
|
|
return count_mounts(m->mnt_ns, child);
|
|
}
|
|
|
|
/*
|
|
* mount 'source_mnt' under the destination 'dest_mnt' at
|
|
* dentry 'dest_dentry'. And propagate that mount to
|
|
* all the peer and slave mounts of 'dest_mnt'.
|
|
* Link all the new mounts into a propagation tree headed at
|
|
* source_mnt. Also link all the new mounts using ->mnt_list
|
|
* headed at source_mnt's ->mnt_list
|
|
*
|
|
* @dest_mnt: destination mount.
|
|
* @dest_dentry: destination dentry.
|
|
* @source_mnt: source mount.
|
|
* @tree_list : list of heads of trees to be attached.
|
|
*/
|
|
int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
|
|
struct mount *source_mnt, struct hlist_head *tree_list)
|
|
{
|
|
struct mount *m, *n;
|
|
int ret = 0;
|
|
|
|
/*
|
|
* we don't want to bother passing tons of arguments to
|
|
* propagate_one(); everything is serialized by namespace_sem,
|
|
* so globals will do just fine.
|
|
*/
|
|
user_ns = current->nsproxy->mnt_ns->user_ns;
|
|
last_dest = dest_mnt;
|
|
first_source = source_mnt;
|
|
last_source = source_mnt;
|
|
mp = dest_mp;
|
|
list = tree_list;
|
|
dest_master = dest_mnt->mnt_master;
|
|
|
|
/* all peers of dest_mnt, except dest_mnt itself */
|
|
for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
|
|
ret = propagate_one(n);
|
|
if (ret)
|
|
goto out;
|
|
}
|
|
|
|
/* all slave groups */
|
|
for (m = next_group(dest_mnt, dest_mnt); m;
|
|
m = next_group(m, dest_mnt)) {
|
|
/* everything in that slave group */
|
|
n = m;
|
|
do {
|
|
ret = propagate_one(n);
|
|
if (ret)
|
|
goto out;
|
|
n = next_peer(n);
|
|
} while (n != m);
|
|
}
|
|
out:
|
|
read_seqlock_excl(&mount_lock);
|
|
hlist_for_each_entry(n, tree_list, mnt_hash) {
|
|
m = n->mnt_parent;
|
|
if (m->mnt_master != dest_mnt->mnt_master)
|
|
CLEAR_MNT_MARK(m->mnt_master);
|
|
}
|
|
read_sequnlock_excl(&mount_lock);
|
|
return ret;
|
|
}
|
|
|
|
static struct mount *find_topper(struct mount *mnt)
|
|
{
|
|
/* If there is exactly one mount covering mnt completely return it. */
|
|
struct mount *child;
|
|
|
|
if (!list_is_singular(&mnt->mnt_mounts))
|
|
return NULL;
|
|
|
|
child = list_first_entry(&mnt->mnt_mounts, struct mount, mnt_child);
|
|
if (child->mnt_mountpoint != mnt->mnt.mnt_root)
|
|
return NULL;
|
|
|
|
return child;
|
|
}
|
|
|
|
/*
|
|
* return true if the refcount is greater than count
|
|
*/
|
|
static inline int do_refcount_check(struct mount *mnt, int count)
|
|
{
|
|
return mnt_get_count(mnt) > count;
|
|
}
|
|
|
|
/*
|
|
* check if the mount 'mnt' can be unmounted successfully.
|
|
* @mnt: the mount to be checked for unmount
|
|
* NOTE: unmounting 'mnt' would naturally propagate to all
|
|
* other mounts its parent propagates to.
|
|
* Check if any of these mounts that **do not have submounts**
|
|
* have more references than 'refcnt'. If so return busy.
|
|
*
|
|
* vfsmount lock must be held for write
|
|
*/
|
|
int propagate_mount_busy(struct mount *mnt, int refcnt)
|
|
{
|
|
struct mount *m, *child, *topper;
|
|
struct mount *parent = mnt->mnt_parent;
|
|
|
|
if (mnt == parent)
|
|
return do_refcount_check(mnt, refcnt);
|
|
|
|
/*
|
|
* quickly check if the current mount can be unmounted.
|
|
* If not, we don't have to go checking for all other
|
|
* mounts
|
|
*/
|
|
if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt))
|
|
return 1;
|
|
|
|
for (m = propagation_next(parent, parent); m;
|
|
m = propagation_next(m, parent)) {
|
|
int count = 1;
|
|
child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
|
|
if (!child)
|
|
continue;
|
|
|
|
/* Is there exactly one mount on the child that covers
|
|
* it completely whose reference should be ignored?
|
|
*/
|
|
topper = find_topper(child);
|
|
if (topper)
|
|
count += 1;
|
|
else if (!list_empty(&child->mnt_mounts))
|
|
continue;
|
|
|
|
if (do_refcount_check(child, count))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Clear MNT_LOCKED when it can be shown to be safe.
|
|
*
|
|
* mount_lock lock must be held for write
|
|
*/
|
|
void propagate_mount_unlock(struct mount *mnt)
|
|
{
|
|
struct mount *parent = mnt->mnt_parent;
|
|
struct mount *m, *child;
|
|
|
|
BUG_ON(parent == mnt);
|
|
|
|
for (m = propagation_next(parent, parent); m;
|
|
m = propagation_next(m, parent)) {
|
|
child = __lookup_mnt(&m->mnt, mnt->mnt_mountpoint);
|
|
if (child)
|
|
child->mnt.mnt_flags &= ~MNT_LOCKED;
|
|
}
|
|
}
|
|
|
|
static void umount_one(struct mount *mnt, struct list_head *to_umount)
|
|
{
|
|
CLEAR_MNT_MARK(mnt);
|
|
mnt->mnt.mnt_flags |= MNT_UMOUNT;
|
|
list_del_init(&mnt->mnt_child);
|
|
list_del_init(&mnt->mnt_umounting);
|
|
list_move_tail(&mnt->mnt_list, to_umount);
|
|
}
|
|
|
|
/*
|
|
* NOTE: unmounting 'mnt' naturally propagates to all other mounts its
|
|
* parent propagates to.
|
|
*/
|
|
static bool __propagate_umount(struct mount *mnt,
|
|
struct list_head *to_umount,
|
|
struct list_head *to_restore)
|
|
{
|
|
bool progress = false;
|
|
struct mount *child;
|
|
|
|
/*
|
|
* The state of the parent won't change if this mount is
|
|
* already unmounted or marked as without children.
|
|
*/
|
|
if (mnt->mnt.mnt_flags & (MNT_UMOUNT | MNT_MARKED))
|
|
goto out;
|
|
|
|
/* Verify topper is the only grandchild that has not been
|
|
* speculatively unmounted.
|
|
*/
|
|
list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
|
|
if (child->mnt_mountpoint == mnt->mnt.mnt_root)
|
|
continue;
|
|
if (!list_empty(&child->mnt_umounting) && IS_MNT_MARKED(child))
|
|
continue;
|
|
/* Found a mounted child */
|
|
goto children;
|
|
}
|
|
|
|
/* Mark mounts that can be unmounted if not locked */
|
|
SET_MNT_MARK(mnt);
|
|
progress = true;
|
|
|
|
/* If a mount is without children and not locked umount it. */
|
|
if (!IS_MNT_LOCKED(mnt)) {
|
|
umount_one(mnt, to_umount);
|
|
} else {
|
|
children:
|
|
list_move_tail(&mnt->mnt_umounting, to_restore);
|
|
}
|
|
out:
|
|
return progress;
|
|
}
|
|
|
|
static void umount_list(struct list_head *to_umount,
|
|
struct list_head *to_restore)
|
|
{
|
|
struct mount *mnt, *child, *tmp;
|
|
list_for_each_entry(mnt, to_umount, mnt_list) {
|
|
list_for_each_entry_safe(child, tmp, &mnt->mnt_mounts, mnt_child) {
|
|
/* topper? */
|
|
if (child->mnt_mountpoint == mnt->mnt.mnt_root)
|
|
list_move_tail(&child->mnt_umounting, to_restore);
|
|
else
|
|
umount_one(child, to_umount);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void restore_mounts(struct list_head *to_restore)
|
|
{
|
|
/* Restore mounts to a clean working state */
|
|
while (!list_empty(to_restore)) {
|
|
struct mount *mnt, *parent;
|
|
struct mountpoint *mp;
|
|
|
|
mnt = list_first_entry(to_restore, struct mount, mnt_umounting);
|
|
CLEAR_MNT_MARK(mnt);
|
|
list_del_init(&mnt->mnt_umounting);
|
|
|
|
/* Should this mount be reparented? */
|
|
mp = mnt->mnt_mp;
|
|
parent = mnt->mnt_parent;
|
|
while (parent->mnt.mnt_flags & MNT_UMOUNT) {
|
|
mp = parent->mnt_mp;
|
|
parent = parent->mnt_parent;
|
|
}
|
|
if (parent != mnt->mnt_parent)
|
|
mnt_change_mountpoint(parent, mp, mnt);
|
|
}
|
|
}
|
|
|
|
static void cleanup_umount_visitations(struct list_head *visited)
|
|
{
|
|
while (!list_empty(visited)) {
|
|
struct mount *mnt =
|
|
list_first_entry(visited, struct mount, mnt_umounting);
|
|
list_del_init(&mnt->mnt_umounting);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* collect all mounts that receive propagation from the mount in @list,
|
|
* and return these additional mounts in the same list.
|
|
* @list: the list of mounts to be unmounted.
|
|
*
|
|
* vfsmount lock must be held for write
|
|
*/
|
|
int propagate_umount(struct list_head *list)
|
|
{
|
|
struct mount *mnt;
|
|
LIST_HEAD(to_restore);
|
|
LIST_HEAD(to_umount);
|
|
LIST_HEAD(visited);
|
|
|
|
/* Find candidates for unmounting */
|
|
list_for_each_entry_reverse(mnt, list, mnt_list) {
|
|
struct mount *parent = mnt->mnt_parent;
|
|
struct mount *m;
|
|
|
|
/*
|
|
* If this mount has already been visited it is known that it's
|
|
* entire peer group and all of their slaves in the propagation
|
|
* tree for the mountpoint has already been visited and there is
|
|
* no need to visit them again.
|
|
*/
|
|
if (!list_empty(&mnt->mnt_umounting))
|
|
continue;
|
|
|
|
list_add_tail(&mnt->mnt_umounting, &visited);
|
|
for (m = propagation_next(parent, parent); m;
|
|
m = propagation_next(m, parent)) {
|
|
struct mount *child = __lookup_mnt(&m->mnt,
|
|
mnt->mnt_mountpoint);
|
|
if (!child)
|
|
continue;
|
|
|
|
if (!list_empty(&child->mnt_umounting)) {
|
|
/*
|
|
* If the child has already been visited it is
|
|
* know that it's entire peer group and all of
|
|
* their slaves in the propgation tree for the
|
|
* mountpoint has already been visited and there
|
|
* is no need to visit this subtree again.
|
|
*/
|
|
m = skip_propagation_subtree(m, parent);
|
|
continue;
|
|
} else if (child->mnt.mnt_flags & MNT_UMOUNT) {
|
|
/*
|
|
* We have come accross an partially unmounted
|
|
* mount in list that has not been visited yet.
|
|
* Remember it has been visited and continue
|
|
* about our merry way.
|
|
*/
|
|
list_add_tail(&child->mnt_umounting, &visited);
|
|
continue;
|
|
}
|
|
|
|
/* Check the child and parents while progress is made */
|
|
while (__propagate_umount(child,
|
|
&to_umount, &to_restore)) {
|
|
/* Is the parent a umount candidate? */
|
|
child = child->mnt_parent;
|
|
if (list_empty(&child->mnt_umounting))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
umount_list(&to_umount, &to_restore);
|
|
restore_mounts(&to_restore);
|
|
cleanup_umount_visitations(&visited);
|
|
list_splice_tail(&to_umount, list);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void propagate_remount(struct mount *mnt)
|
|
{
|
|
struct mount *parent = mnt->mnt_parent;
|
|
struct mount *p = mnt, *m;
|
|
struct super_block *sb = mnt->mnt.mnt_sb;
|
|
|
|
if (!sb->s_op->copy_mnt_data)
|
|
return;
|
|
for (p = propagation_next(parent, parent); p;
|
|
p = propagation_next(p, parent)) {
|
|
m = __lookup_mnt(&p->mnt, mnt->mnt_mountpoint);
|
|
if (m)
|
|
sb->s_op->copy_mnt_data(m->mnt.data, mnt->mnt.data);
|
|
}
|
|
}
|