Changes in 4.9.334 HID: hyperv: fix possible memory leak in mousevsc_probe() net: gso: fix panic on frag_list with mixed head alloc types bnxt_en: fix potentially incorrect return value for ndo_rx_flow_steer net: fman: Unregister ethernet device on removal capabilities: fix undefined behavior in bit shift for CAP_TO_MASK net: lapbether: fix issue of dev reference count leakage in lapbeth_device_event() hamradio: fix issue of dev reference count leakage in bpq_device_event() ipv6: addrlabel: fix infoleak when sending struct ifaddrlblmsg to network tipc: fix the msg->req tlv len check in tipc_nl_compat_name_table_dump_header dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove() drivers: net: xgene: disable napi when register irq failed in xgene_enet_open() net: cxgb3_main: disable napi when bind qsets failed in cxgb_up() ethernet: s2io: disable napi when start nic failed in s2io_card_up() net: mv643xx_eth: disable napi when init rxq or txq failed in mv643xx_eth_open() net: macvlan: fix memory leaks of macvlan_common_newlink ALSA: hda: fix potential memleak in 'add_widget_node' ALSA: usb-audio: Add quirk entry for M-Audio Micro nilfs2: fix deadlock in nilfs_count_free_blocks() platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi btrfs: selftests: fix wrong error check in btrfs_free_dummy_root() udf: Fix a slab-out-of-bounds write bug in udf_find_entry() cert host tools: Stop complaining about deprecated OpenSSL functions dmaengine: at_hdmac: Fix at_lli struct definition dmaengine: at_hdmac: Don't start transactions at tx_submit level dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors dmaengine: at_hdmac: Don't allow CPU to reorder channel enable dmaengine: at_hdmac: Fix impossible condition dmaengine: at_hdmac: Check return code of dma_async_device_register x86/cpu: Restore AMD's DE_CFG MSR after resume drm/imx: imx-tve: Fix return type of imx_tve_connector_mode_valid Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm ASoC: core: Fix use-after-free in snd_soc_exit() serial: 8250_omap: remove wait loop from Errata i202 workaround serial: 8250: omap: Flush PM QOS work on remove tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send ASoC: soc-utils: Remove __exit for snd_soc_util_exit() parport_pc: Avoid FIFO port location truncation pinctrl: devicetree: fix null pointer dereferencing in pinctrl_dt_to_map mISDN: fix possible memory leak in mISDN_dsp_element_register() mISDN: fix misuse of put_device() in mISDN_register_device() net: caif: fix double disconnect client in chnl_net_open() xen/pcpu: fix possible memory leak in register_pcpu() net/x25: Fix skb leak in x25_lapb_receive_frame() cifs: Fix wrong return value checking when GETFLAGS ftrace: Fix the possible incorrect kernel message ftrace: Optimize the allocation for mcount entries ring_buffer: Do not deactivate non-existant pages ALSA: usb-audio: Drop snd_BUG_ON() from snd_usbmidi_output_open() USB: serial: option: add Sierra Wireless EM9191 USB: serial: option: remove old LARA-R6 PID USB: serial: option: add u-blox LARA-R6 00B modem USB: serial: option: add u-blox LARA-L6 modem USB: serial: option: add Fibocom FM160 0x0111 composition usb: add NO_LPM quirk for Realforce 87U Keyboard usb: chipidea: fix deadlock in ci_otg_del_timer iio: adc: at91_adc: fix possible memory leak in at91_adc_allocate_trigger() iio: trigger: sysfs: fix possible memory leak in iio_sysfs_trig_init() iio: pressure: ms5611: changed hardcoded SPI speed to value limited dm ioctl: fix misbehavior if list_versions races with module loading serial: 8250: Fall back to non-DMA Rx if IIR_RDI occurs serial: 8250_lpss: Configure DMA also w/o DMA filter mmc: core: properly select voltage range without power cycle misc/vmw_vmci: fix an infoleak in vmci_host_do_receive_datagram() nilfs2: fix use-after-free bug of ns_writer on remount serial: 8250: Flush DMA Rx on RLSI tcp: cdg: allow tcp_cdg_release() to be called multiple times kcm: avoid potential race in kcm_tx_work 9p: trans_fd/p9_conn_cancel: drop client lock earlier gfs2: Check sb_bsize_shift after reading superblock gfs2: Switch from strlcpy to strscpy 9p/trans_fd: always use O_NONBLOCK read/write mm: fs: initialize fsdata passed to write_begin/write_end interface ntfs: fix use-after-free in ntfs_attr_find() ntfs: fix out-of-bounds read in ntfs_attr_find() ntfs: check overflow when iterating ATTR_RECORDs Linux 4.9.334 Change-Id: I9e6e907e472831b20a849c7765c0eb2a62694347 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
285 lines
7.2 KiB
C
285 lines
7.2 KiB
C
/*
|
|
* Copyright (C) 2013 Fusion IO. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License v2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 021110-1307, USA.
|
|
*/
|
|
|
|
#include <linux/fs.h>
|
|
#include <linux/mount.h>
|
|
#include <linux/magic.h>
|
|
#include "btrfs-tests.h"
|
|
#include "../ctree.h"
|
|
#include "../free-space-cache.h"
|
|
#include "../free-space-tree.h"
|
|
#include "../transaction.h"
|
|
#include "../volumes.h"
|
|
#include "../disk-io.h"
|
|
#include "../qgroup.h"
|
|
|
|
static struct vfsmount *test_mnt = NULL;
|
|
|
|
static const struct super_operations btrfs_test_super_ops = {
|
|
.alloc_inode = btrfs_alloc_inode,
|
|
.destroy_inode = btrfs_test_destroy_inode,
|
|
};
|
|
|
|
static struct dentry *btrfs_test_mount(struct file_system_type *fs_type,
|
|
int flags, const char *dev_name,
|
|
void *data)
|
|
{
|
|
return mount_pseudo(fs_type, "btrfs_test:", &btrfs_test_super_ops,
|
|
NULL, BTRFS_TEST_MAGIC);
|
|
}
|
|
|
|
static struct file_system_type test_type = {
|
|
.name = "btrfs_test_fs",
|
|
.mount = btrfs_test_mount,
|
|
.kill_sb = kill_anon_super,
|
|
};
|
|
|
|
struct inode *btrfs_new_test_inode(void)
|
|
{
|
|
struct inode *inode;
|
|
|
|
inode = new_inode(test_mnt->mnt_sb);
|
|
if (inode)
|
|
inode_init_owner(inode, NULL, S_IFREG);
|
|
|
|
return inode;
|
|
}
|
|
|
|
static int btrfs_init_test_fs(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = register_filesystem(&test_type);
|
|
if (ret) {
|
|
printk(KERN_ERR "btrfs: cannot register test file system\n");
|
|
return ret;
|
|
}
|
|
|
|
test_mnt = kern_mount(&test_type);
|
|
if (IS_ERR(test_mnt)) {
|
|
printk(KERN_ERR "btrfs: cannot mount test file system\n");
|
|
unregister_filesystem(&test_type);
|
|
return PTR_ERR(test_mnt);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void btrfs_destroy_test_fs(void)
|
|
{
|
|
kern_unmount(test_mnt);
|
|
unregister_filesystem(&test_type);
|
|
}
|
|
|
|
struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void)
|
|
{
|
|
struct btrfs_fs_info *fs_info = kzalloc(sizeof(struct btrfs_fs_info),
|
|
GFP_KERNEL);
|
|
|
|
if (!fs_info)
|
|
return fs_info;
|
|
fs_info->fs_devices = kzalloc(sizeof(struct btrfs_fs_devices),
|
|
GFP_KERNEL);
|
|
if (!fs_info->fs_devices) {
|
|
kfree(fs_info);
|
|
return NULL;
|
|
}
|
|
fs_info->super_copy = kzalloc(sizeof(struct btrfs_super_block),
|
|
GFP_KERNEL);
|
|
if (!fs_info->super_copy) {
|
|
kfree(fs_info->fs_devices);
|
|
kfree(fs_info);
|
|
return NULL;
|
|
}
|
|
|
|
if (init_srcu_struct(&fs_info->subvol_srcu)) {
|
|
kfree(fs_info->fs_devices);
|
|
kfree(fs_info->super_copy);
|
|
kfree(fs_info);
|
|
return NULL;
|
|
}
|
|
|
|
spin_lock_init(&fs_info->buffer_lock);
|
|
spin_lock_init(&fs_info->qgroup_lock);
|
|
spin_lock_init(&fs_info->qgroup_op_lock);
|
|
spin_lock_init(&fs_info->super_lock);
|
|
spin_lock_init(&fs_info->fs_roots_radix_lock);
|
|
mutex_init(&fs_info->qgroup_ioctl_lock);
|
|
mutex_init(&fs_info->qgroup_rescan_lock);
|
|
rwlock_init(&fs_info->tree_mod_log_lock);
|
|
fs_info->running_transaction = NULL;
|
|
fs_info->qgroup_tree = RB_ROOT;
|
|
fs_info->qgroup_ulist = NULL;
|
|
atomic64_set(&fs_info->tree_mod_seq, 0);
|
|
INIT_LIST_HEAD(&fs_info->dirty_qgroups);
|
|
INIT_LIST_HEAD(&fs_info->dead_roots);
|
|
INIT_LIST_HEAD(&fs_info->tree_mod_seq_list);
|
|
INIT_RADIX_TREE(&fs_info->buffer_radix, GFP_ATOMIC);
|
|
INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
|
|
extent_io_tree_init(&fs_info->freed_extents[0], NULL);
|
|
extent_io_tree_init(&fs_info->freed_extents[1], NULL);
|
|
fs_info->pinned_extents = &fs_info->freed_extents[0];
|
|
set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
|
|
|
|
test_mnt->mnt_sb->s_fs_info = fs_info;
|
|
|
|
return fs_info;
|
|
}
|
|
|
|
void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
|
|
{
|
|
struct radix_tree_iter iter;
|
|
void **slot;
|
|
|
|
if (!fs_info)
|
|
return;
|
|
|
|
if (WARN_ON(!test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO,
|
|
&fs_info->fs_state)))
|
|
return;
|
|
|
|
test_mnt->mnt_sb->s_fs_info = NULL;
|
|
|
|
spin_lock(&fs_info->buffer_lock);
|
|
radix_tree_for_each_slot(slot, &fs_info->buffer_radix, &iter, 0) {
|
|
struct extent_buffer *eb;
|
|
|
|
eb = radix_tree_deref_slot_protected(slot, &fs_info->buffer_lock);
|
|
if (!eb)
|
|
continue;
|
|
/* Shouldn't happen but that kind of thinking creates CVE's */
|
|
if (radix_tree_exception(eb)) {
|
|
if (radix_tree_deref_retry(eb))
|
|
slot = radix_tree_iter_retry(&iter);
|
|
continue;
|
|
}
|
|
spin_unlock(&fs_info->buffer_lock);
|
|
free_extent_buffer_stale(eb);
|
|
spin_lock(&fs_info->buffer_lock);
|
|
}
|
|
spin_unlock(&fs_info->buffer_lock);
|
|
|
|
btrfs_free_qgroup_config(fs_info);
|
|
btrfs_free_fs_roots(fs_info);
|
|
cleanup_srcu_struct(&fs_info->subvol_srcu);
|
|
kfree(fs_info->super_copy);
|
|
kfree(fs_info->fs_devices);
|
|
kfree(fs_info);
|
|
}
|
|
|
|
void btrfs_free_dummy_root(struct btrfs_root *root)
|
|
{
|
|
if (IS_ERR_OR_NULL(root))
|
|
return;
|
|
/* Will be freed by btrfs_free_fs_roots */
|
|
if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
|
|
return;
|
|
if (root->node)
|
|
free_extent_buffer(root->node);
|
|
kfree(root);
|
|
}
|
|
|
|
struct btrfs_block_group_cache *
|
|
btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize)
|
|
{
|
|
struct btrfs_block_group_cache *cache;
|
|
|
|
cache = kzalloc(sizeof(*cache), GFP_KERNEL);
|
|
if (!cache)
|
|
return NULL;
|
|
cache->free_space_ctl = kzalloc(sizeof(*cache->free_space_ctl),
|
|
GFP_KERNEL);
|
|
if (!cache->free_space_ctl) {
|
|
kfree(cache);
|
|
return NULL;
|
|
}
|
|
|
|
cache->key.objectid = 0;
|
|
cache->key.offset = length;
|
|
cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
|
|
cache->sectorsize = sectorsize;
|
|
cache->full_stripe_len = sectorsize;
|
|
|
|
INIT_LIST_HEAD(&cache->list);
|
|
INIT_LIST_HEAD(&cache->cluster_list);
|
|
INIT_LIST_HEAD(&cache->bg_list);
|
|
btrfs_init_free_space_ctl(cache);
|
|
mutex_init(&cache->free_space_lock);
|
|
|
|
return cache;
|
|
}
|
|
|
|
void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache)
|
|
{
|
|
if (!cache)
|
|
return;
|
|
__btrfs_remove_free_space_cache(cache->free_space_ctl);
|
|
kfree(cache->free_space_ctl);
|
|
kfree(cache);
|
|
}
|
|
|
|
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans)
|
|
{
|
|
memset(trans, 0, sizeof(*trans));
|
|
trans->transid = 1;
|
|
INIT_LIST_HEAD(&trans->qgroup_ref_list);
|
|
trans->type = __TRANS_DUMMY;
|
|
}
|
|
|
|
int btrfs_run_sanity_tests(void)
|
|
{
|
|
int ret, i;
|
|
u32 sectorsize, nodesize;
|
|
u32 test_sectorsize[] = {
|
|
PAGE_SIZE,
|
|
};
|
|
ret = btrfs_init_test_fs();
|
|
if (ret)
|
|
return ret;
|
|
for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
|
|
sectorsize = test_sectorsize[i];
|
|
for (nodesize = sectorsize;
|
|
nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
|
|
nodesize <<= 1) {
|
|
pr_info("BTRFS: selftest: sectorsize: %u nodesize: %u\n",
|
|
sectorsize, nodesize);
|
|
ret = btrfs_test_free_space_cache(sectorsize, nodesize);
|
|
if (ret)
|
|
goto out;
|
|
ret = btrfs_test_extent_buffer_operations(sectorsize,
|
|
nodesize);
|
|
if (ret)
|
|
goto out;
|
|
ret = btrfs_test_extent_io(sectorsize, nodesize);
|
|
if (ret)
|
|
goto out;
|
|
ret = btrfs_test_inodes(sectorsize, nodesize);
|
|
if (ret)
|
|
goto out;
|
|
ret = btrfs_test_qgroups(sectorsize, nodesize);
|
|
if (ret)
|
|
goto out;
|
|
ret = btrfs_test_free_space_tree(sectorsize, nodesize);
|
|
if (ret)
|
|
goto out;
|
|
}
|
|
}
|
|
out:
|
|
btrfs_destroy_test_fs();
|
|
return ret;
|
|
}
|