From 08dc6f4aea5eac386ac0320779fe9f7d06f46a37 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Wed, 22 Jul 2015 18:04:50 +0300 Subject: [PATCH] Changes representative of linux-3.10.0-229.11.1.el7.tar.xz --- Makefile | 2 +- arch/powerpc/include/asm/rtas.h | 2 +- arch/powerpc/kernel/rtas.c | 26 ++--- arch/powerpc/platforms/pseries/iommu.c | 51 +++++---- arch/powerpc/platforms/pseries/mobility.c | 70 +++++++----- arch/s390/crypto/ghash_s390.c | 25 ++--- arch/x86/kernel/kvm.c | 8 ++ arch/x86/kernel/microcode_intel_early.c | 2 +- crypto/Makefile | 1 - crypto/chainiv.c | 66 ++---------- crypto/drbg.c | 3 +- crypto/eseqiv.c | 29 +---- crypto/krng.c | 65 ----------- crypto/seqiv.c | 58 ++-------- drivers/infiniband/core/cma.c | 2 +- drivers/of/base.c | 57 +++++----- drivers/scsi/ipr.h | 2 +- drivers/usb/core/hcd.c | 16 +-- fs/ext4/extents_status.c | 8 ++ fs/ext4/inode.c | 2 + fs/fscache/page.c | 10 +- fs/nfs/nfs4state.c | 1 + include/linux/ceph/libceph.h | 3 +- include/linux/ceph/messenger.h | 4 +- include/linux/fscache-cache.h | 7 +- include/linux/nmi.h | 13 +++ include/linux/of.h | 6 +- include/net/ip.h | 6 +- include/net/net_namespace.h | 2 + include/net/netfilter/nf_conntrack_extend.h | 4 +- include/net/netns/ipv4.h | 5 + include/net/udp.h | 4 +- kernel/module.c | 3 + kernel/watchdog.c | 114 ++++++++++++++++++-- net/ceph/ceph_common.c | 15 ++- net/ceph/messenger.c | 14 ++- net/ceph/osd_client.c | 26 +++-- net/ipv4/inet_connection_sock.c | 20 ++-- net/ipv4/inet_hashtables.c | 2 +- net/ipv4/ping.c | 5 +- net/ipv4/sysctl_net_ipv4.c | 52 +++++---- net/ipv4/udp.c | 2 +- net/ipv6/ndisc.c | 9 +- net/sctp/socket.c | 2 +- net/sunrpc/clnt.c | 3 + security/selinux/hooks.c | 2 +- 46 files changed, 432 insertions(+), 397 deletions(-) delete mode 100644 crypto/krng.c diff --git a/Makefile b/Makefile index 915f1a170bf522..cff52f41146c62 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ EXTRAVERSION = NAME = Unicycling Gorilla RHEL_MAJOR = 7 RHEL_MINOR = 1 -RHEL_RELEASE = 229.7.2 +RHEL_RELEASE = 229.11.1 RHEL_DRM_VERSION = 3 RHEL_DRM_PATCHLEVEL = 16 RHEL_DRM_SUBLEVEL = 7 diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 2e23e92a43722f..fc85eb0d57636f 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -327,7 +327,7 @@ extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); extern int rtas_online_cpus_mask(cpumask_var_t cpus); extern int rtas_offline_cpus_mask(cpumask_var_t cpus); -extern int rtas_ibm_suspend_me(u64 handle, int *vasi_return); +extern int rtas_ibm_suspend_me(u64 handle); struct rtc_time; extern unsigned long rtas_get_boot_time(void); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 305d962d1f4450..18f1cc0b04ffc8 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -897,7 +897,7 @@ int rtas_offline_cpus_mask(cpumask_var_t cpus) } EXPORT_SYMBOL(rtas_offline_cpus_mask); -int rtas_ibm_suspend_me(u64 handle, int *vasi_return) +int rtas_ibm_suspend_me(u64 handle) { long state; long rc; @@ -919,13 +919,11 @@ int rtas_ibm_suspend_me(u64 handle, int *vasi_return) printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); return rc; } else if (state == H_VASI_ENABLED) { - *vasi_return = RTAS_NOT_SUSPENDABLE; - return 0; + return -EAGAIN; } else if (state != H_VASI_SUSPENDING) { printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", state); - *vasi_return = -1; - return 0; + return -EIO; } if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) @@ -972,7 +970,7 @@ int rtas_ibm_suspend_me(u64 handle, int *vasi_return) return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ -int rtas_ibm_suspend_me(u64 handle, int *vasi_return) +int rtas_ibm_suspend_me(u64 handle) { return -ENOSYS; } @@ -1022,7 +1020,6 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) unsigned long flags; char *buff_copy, *errbuf = NULL; int nargs, nret, token; - int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1054,15 +1051,18 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) if (token == ibm_suspend_me_token) { /* - * rtas_ibm_suspend_me assumes args are in cpu endian, or at least the - * hcall within it requires it. + * rtas_ibm_suspend_me assumes the streamid handle is in cpu + * endian, or at least the hcall within it requires it. */ - int vasi_rc = 0; + int rc = 0; u64 handle = ((u64)be32_to_cpu(args.args[0]) << 32) | be32_to_cpu(args.args[1]); - rc = rtas_ibm_suspend_me(handle, &vasi_rc); - args.rets[0] = cpu_to_be32(vasi_rc); - if (rc) + rc = rtas_ibm_suspend_me(handle); + if (rc == -EAGAIN) + args.rets[0] = cpu_to_be32(RTAS_NOT_SUSPENDABLE); + else if (rc == -EIO) + args.rets[0] = cpu_to_be32(-1); + else if (rc) return rc; goto copy_return; } diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index bd49cf2c9a5dc7..7ff45b25032fa2 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -329,16 +329,16 @@ struct direct_window { /* Dynamic DMA Window support */ struct ddw_query_response { - __be32 windows_available; - __be32 largest_available_block; - __be32 page_size; - __be32 migration_capable; + u32 windows_available; + u32 largest_available_block; + u32 page_size; + u32 migration_capable; }; struct ddw_create_response { - __be32 liobn; - __be32 addr_hi; - __be32 addr_lo; + u32 liobn; + u32 addr_hi; + u32 addr_lo; }; static LIST_HEAD(direct_window_list); @@ -725,16 +725,18 @@ static void remove_ddw(struct device_node *np) { struct dynamic_dma_window_prop *dwp; struct property *win64; - const u32 *ddw_avail; + u32 ddw_avail[3]; u64 liobn; - int len, ret; + int ret = 0; + + ret = of_property_read_u32_array(np, "ibm,ddw-applicable", + &ddw_avail[0], 3); - ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); if (!win64) return; - if (!ddw_avail || len < 3 * sizeof(u32) || win64->length < sizeof(*dwp)) + if (ret || win64->length < sizeof(*dwp)) goto delprop; dwp = win64->value; @@ -871,8 +873,9 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, do { /* extra outputs are LIOBN and dma-addr (hi, lo) */ - ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, cfg_addr, - BUID_HI(buid), BUID_LO(buid), page_shift, window_shift); + ret = rtas_call(ddw_avail[1], 5, 4, (u32 *)create, + cfg_addr, BUID_HI(buid), BUID_LO(buid), + page_shift, window_shift); } while (rtas_busy_delay(ret)); dev_info(&dev->dev, "ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d " @@ -909,7 +912,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) int page_shift; u64 dma_addr, max_addr; struct device_node *dn; - const u32 *uninitialized_var(ddw_avail); + u32 ddw_avail[3]; struct direct_window *window; struct property *win64; struct dynamic_dma_window_prop *ddwprop; @@ -941,8 +944,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) * for the given node in that order. * the property is actually in the parent, not the PE */ - ddw_avail = of_get_property(pdn, "ibm,ddw-applicable", &len); - if (!ddw_avail || len < 3 * sizeof(u32)) + ret = of_property_read_u32_array(pdn, "ibm,ddw-applicable", + &ddw_avail[0], 3); + if (ret) goto out_failed; /* @@ -965,11 +969,11 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) dev_dbg(&dev->dev, "no free dynamic windows"); goto out_failed; } - if (be32_to_cpu(query.page_size) & 4) { + if (query.page_size & 4) { page_shift = 24; /* 16MB */ - } else if (be32_to_cpu(query.page_size) & 2) { + } else if (query.page_size & 2) { page_shift = 16; /* 64kB */ - } else if (be32_to_cpu(query.page_size) & 1) { + } else if (query.page_size & 1) { page_shift = 12; /* 4kB */ } else { dev_dbg(&dev->dev, "no supported direct page size in mask %x", @@ -979,7 +983,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) /* verify the window * number of ptes will map the partition */ /* check largest block * page size > max memory hotplug addr */ max_addr = memory_hotplug_max(); - if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) { + if (query.largest_available_block < (max_addr >> page_shift)) { dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " "%llu-sized pages\n", max_addr, query.largest_available_block, 1ULL << page_shift); @@ -1005,8 +1009,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) if (ret != 0) goto out_free_prop; - ddwprop->liobn = create.liobn; - ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2)); + ddwprop->liobn = cpu_to_be32(create.liobn); + ddwprop->dma_base = cpu_to_be64(((u64)create.addr_hi << 32) | + create.addr_lo); ddwprop->tce_shift = cpu_to_be32(page_shift); ddwprop->window_shift = cpu_to_be32(len); @@ -1038,7 +1043,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) list_add(&window->list, &direct_window_list); spin_unlock(&direct_window_list_lock); - dma_addr = of_read_number(&create.addr_hi, 2); + dma_addr = be64_to_cpu(ddwprop->dma_base); goto out_unlock; out_free_window: diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 450c6c6147d3e7..d06db366e0602c 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -24,10 +24,10 @@ static struct kobject *mobility_kobj; struct update_props_workarea { - u32 phandle; - u32 state; - u64 reserved; - u32 nprops; + __be32 phandle; + __be32 state; + __be64 reserved; + __be32 nprops; } __packed; #define NODE_ACTION_MASK 0xff000000 @@ -53,11 +53,11 @@ static int mobility_rtas_call(int token, char *buf, s32 scope) return rc; } -static int delete_dt_node(u32 phandle) +static int delete_dt_node(__be32 phandle) { struct device_node *dn; - dn = of_find_node_by_phandle(phandle); + dn = of_find_node_by_phandle(be32_to_cpu(phandle)); if (!dn) return -ENOENT; @@ -126,7 +126,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, return 0; } -static int update_dt_node(u32 phandle, s32 scope) +static int update_dt_node(__be32 phandle, s32 scope) { struct update_props_workarea *upwa; struct device_node *dn; @@ -135,6 +135,7 @@ static int update_dt_node(u32 phandle, s32 scope) char *prop_data; char *rtas_buf; int update_properties_token; + u32 nprops; u32 vd; update_properties_token = rtas_token("ibm,update-properties"); @@ -145,7 +146,7 @@ static int update_dt_node(u32 phandle, s32 scope) if (!rtas_buf) return -ENOMEM; - dn = of_find_node_by_phandle(phandle); + dn = of_find_node_by_phandle(be32_to_cpu(phandle)); if (!dn) { kfree(rtas_buf); return -ENOENT; @@ -161,6 +162,7 @@ static int update_dt_node(u32 phandle, s32 scope) break; prop_data = rtas_buf + sizeof(*upwa); + nprops = be32_to_cpu(upwa->nprops); /* On the first call to ibm,update-properties for a node the * the first property value descriptor contains an empty @@ -169,17 +171,17 @@ static int update_dt_node(u32 phandle, s32 scope) */ if (*prop_data == 0) { prop_data++; - vd = *(u32 *)prop_data; + vd = be32_to_cpu(*(__be32 *)prop_data); prop_data += vd + sizeof(vd); - upwa->nprops--; + nprops--; } - for (i = 0; i < upwa->nprops; i++) { + for (i = 0; i < nprops; i++) { char *prop_name; prop_name = prop_data; prop_data += strlen(prop_name) + 1; - vd = *(u32 *)prop_data; + vd = be32_to_cpu(*(__be32 *)prop_data); prop_data += sizeof(vd); switch (vd) { @@ -211,13 +213,13 @@ static int update_dt_node(u32 phandle, s32 scope) return 0; } -static int add_dt_node(u32 parent_phandle, u32 drc_index) +static int add_dt_node(__be32 parent_phandle, __be32 drc_index) { struct device_node *dn; struct device_node *parent_dn; int rc; - parent_dn = of_find_node_by_phandle(parent_phandle); + parent_dn = of_find_node_by_phandle(be32_to_cpu(parent_phandle)); if (!parent_dn) return -ENOENT; @@ -236,7 +238,7 @@ static int add_dt_node(u32 parent_phandle, u32 drc_index) int pseries_devicetree_update(s32 scope) { char *rtas_buf; - u32 *data; + __be32 *data; int update_nodes_token; int rc; @@ -253,17 +255,17 @@ int pseries_devicetree_update(s32 scope) if (rc && rc != 1) break; - data = (u32 *)rtas_buf + 4; - while (*data & NODE_ACTION_MASK) { + data = (__be32 *)rtas_buf + 4; + while (be32_to_cpu(*data) & NODE_ACTION_MASK) { int i; - u32 action = *data & NODE_ACTION_MASK; - int node_count = *data & NODE_COUNT_MASK; + u32 action = be32_to_cpu(*data) & NODE_ACTION_MASK; + u32 node_count = be32_to_cpu(*data) & NODE_COUNT_MASK; data++; for (i = 0; i < node_count; i++) { - u32 phandle = *data++; - u32 drc_index; + __be32 phandle = *data++; + __be32 drc_index; switch (action) { case DELETE_DT_NODE: @@ -317,28 +319,34 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr, { u64 streamid; int rc; - int vasi_rc = 0; rc = strict_strtoull(buf, 0, &streamid); if (rc) return rc; do { - rc = rtas_ibm_suspend_me(streamid, &vasi_rc); - if (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE) + rc = rtas_ibm_suspend_me(streamid); + if (rc == -EAGAIN) ssleep(1); - } while (!rc && vasi_rc == RTAS_NOT_SUSPENDABLE); + } while (rc == -EAGAIN); if (rc) return rc; - if (vasi_rc) - return vasi_rc; post_mobility_fixup(); return count; } +/* + * Used by drmgr to determine the kernel behavior of the migration interface. + * + * Version 1: Performs all PAPR requirements for migration including + * firmware activation and device tree update. + */ +#define MIGRATION_API_VERSION 1 + static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store); +static CLASS_ATTR_STRING(api_version, S_IRUGO, __stringify(MIGRATION_API_VERSION)); static int __init mobility_sysfs_init(void) { @@ -349,7 +357,13 @@ static int __init mobility_sysfs_init(void) return -ENOMEM; rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr); + if (rc) + pr_err("mobility: unable to create migration sysfs file (%d)\n", rc); - return rc; + rc = sysfs_create_file(mobility_kobj, &class_attr_api_version.attr.attr); + if (rc) + pr_err("mobility: unable to create api_version sysfs file (%d)\n", rc); + + return 0; } device_initcall(mobility_sysfs_init); diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c index d43485d142e911..732379ed097523 100644 --- a/arch/s390/crypto/ghash_s390.c +++ b/arch/s390/crypto/ghash_s390.c @@ -16,11 +16,12 @@ #define GHASH_DIGEST_SIZE 16 struct ghash_ctx { - u8 icv[16]; - u8 key[16]; + u8 key[GHASH_BLOCK_SIZE]; }; struct ghash_desc_ctx { + u8 icv[GHASH_BLOCK_SIZE]; + u8 key[GHASH_BLOCK_SIZE]; u8 buffer[GHASH_BLOCK_SIZE]; u32 bytes; }; @@ -28,8 +29,10 @@ struct ghash_desc_ctx { static int ghash_init(struct shash_desc *desc) { struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); + struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); memset(dctx, 0, sizeof(*dctx)); + memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE); return 0; } @@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm, } memcpy(ctx->key, key, GHASH_BLOCK_SIZE); - memset(ctx->icv, 0, GHASH_BLOCK_SIZE); return 0; } @@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc, const u8 *src, unsigned int srclen) { struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); - struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); unsigned int n; u8 *buf = dctx->buffer; int ret; @@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc, src += n; if (!dctx->bytes) { - ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, + ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); if (ret != GHASH_BLOCK_SIZE) return -EIO; @@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc, n = srclen & ~(GHASH_BLOCK_SIZE - 1); if (n) { - ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); + ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n); if (ret != n) return -EIO; src += n; @@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc, return 0; } -static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) +static int ghash_flush(struct ghash_desc_ctx *dctx) { u8 *buf = dctx->buffer; int ret; @@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) memset(pos, 0, dctx->bytes); - ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); + ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE); if (ret != GHASH_BLOCK_SIZE) return -EIO; + + dctx->bytes = 0; } - dctx->bytes = 0; return 0; } static int ghash_final(struct shash_desc *desc, u8 *dst) { struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); - struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); int ret; - ret = ghash_flush(ctx, dctx); + ret = ghash_flush(dctx); if (!ret) - memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); + memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE); return ret; } diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index c2a7cc3be537ff..afa95ff67e485a 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -497,6 +498,13 @@ void __init kvm_guest_init(void) #else kvm_guest_cpu_init(); #endif + + /* + * Hard lockup detection is enabled by default. Disable it, as guests + * can get false positives too easily, for example if the host is + * overcommitted. + */ + watchdog_enable_hardlockup_detector(false); } static noinline uint32_t __kvm_cpuid_base(void) diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c index 1575deb2e636af..c44f7db7ce4459 100644 --- a/arch/x86/kernel/microcode_intel_early.c +++ b/arch/x86/kernel/microcode_intel_early.c @@ -321,7 +321,7 @@ get_matching_model_microcode(int cpu, unsigned long start, unsigned int mc_saved_count = mc_saved_data->mc_saved_count; int i; - while (leftover) { + while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { mc_header = (struct microcode_header_intel *)ucode_ptr; mc_size = get_totalsize(mc_header); diff --git a/crypto/Makefile b/crypto/Makefile index ce40738cc8a4fa..e574b40bc735e0 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -89,7 +89,6 @@ obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o obj-$(CONFIG_CRYPTO_842) += 842.o obj-$(CONFIG_CRYPTO_RNG2) += rng.o -obj-$(CONFIG_CRYPTO_RNG2) += krng.o obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o obj-$(CONFIG_CRYPTO_DRBG) += drbg.o obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o diff --git a/crypto/chainiv.c b/crypto/chainiv.c index 834d8dd3d4fc7a..0d82e84ec2dcf1 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -80,35 +80,15 @@ static int chainiv_givencrypt(struct skcipher_givcrypt_request *req) return err; } -static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) +static int chainiv_init_common(struct crypto_tfm *tfm, char iv[]) { - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - spin_lock_bh(&ctx->lock); - if (crypto_ablkcipher_crt(geniv)->givencrypt != - chainiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - spin_unlock_bh(&ctx->lock); + struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - if (err) - return err; - - return chainiv_givencrypt(req); -} - -static int chainiv_init_common(struct crypto_tfm *tfm) -{ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); - return skcipher_geniv_init(tfm); + return crypto_rng_get_bytes(crypto_default_rng, iv, + crypto_ablkcipher_ivsize(geniv)) ?: + skcipher_geniv_init(tfm); } static int chainiv_init(struct crypto_tfm *tfm) @@ -117,7 +97,7 @@ static int chainiv_init(struct crypto_tfm *tfm) spin_lock_init(&ctx->lock); - return chainiv_init_common(tfm); + return chainiv_init_common(tfm, ctx->iv); } static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx) @@ -205,33 +185,6 @@ static int async_chainiv_givencrypt(struct skcipher_givcrypt_request *req) return async_chainiv_postpone_request(req); } -static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) - goto out; - - if (crypto_ablkcipher_crt(geniv)->givencrypt != - async_chainiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->iv, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - clear_bit(CHAINIV_STATE_INUSE, &ctx->state); - - if (err) - return err; - -out: - return async_chainiv_givencrypt(req); -} - static void async_chainiv_do_postponed(struct work_struct *work) { struct async_chainiv_ctx *ctx = container_of(work, @@ -270,7 +223,7 @@ static int async_chainiv_init(struct crypto_tfm *tfm) crypto_init_queue(&ctx->queue, 100); INIT_WORK(&ctx->postponed, async_chainiv_do_postponed); - return chainiv_init_common(tfm); + return chainiv_init_common(tfm, ctx->iv); } static void async_chainiv_exit(struct crypto_tfm *tfm) @@ -302,7 +255,7 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) if (IS_ERR(inst)) goto put_rng; - inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt; inst->alg.cra_init = chainiv_init; inst->alg.cra_exit = skcipher_geniv_exit; @@ -312,8 +265,7 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) if (!crypto_requires_sync(algt->type, algt->mask)) { inst->alg.cra_flags |= CRYPTO_ALG_ASYNC; - inst->alg.cra_ablkcipher.givencrypt = - async_chainiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = async_chainiv_givencrypt; inst->alg.cra_init = async_chainiv_init; inst->alg.cra_exit = async_chainiv_exit; diff --git a/crypto/drbg.c b/crypto/drbg.c index 782ca3e1d310d1..cdae597ac0b7dc 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1916,7 +1916,7 @@ static inline void __init drbg_fill_array(struct crypto_alg *alg, const struct drbg_core *core, int pr) { int pos = 0; - static int priority = 100; + static int priority = 200; memset(alg, 0, sizeof(struct crypto_alg)); memcpy(alg->cra_name, "stdrng", 6); @@ -2007,3 +2007,4 @@ MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) " CRYPTO_DRBG_HASH_STRING CRYPTO_DRBG_HMAC_STRING CRYPTO_DRBG_CTR_STRING); +MODULE_ALIAS("stdrng"); diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c index 42ce9f570aecce..b27aca1cd6cf53 100644 --- a/crypto/eseqiv.c +++ b/crypto/eseqiv.c @@ -146,29 +146,6 @@ static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req) return err; } -static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - spin_lock_bh(&ctx->lock); - if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - spin_unlock_bh(&ctx->lock); - - if (err) - return err; - - return eseqiv_givencrypt(req); -} - static int eseqiv_init(struct crypto_tfm *tfm) { struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); @@ -198,7 +175,9 @@ static int eseqiv_init(struct crypto_tfm *tfm) tfm->crt_ablkcipher.reqsize = reqsize + sizeof(struct ablkcipher_request); - return skcipher_geniv_init(tfm); + return crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_ablkcipher_ivsize(geniv)) ?: + skcipher_geniv_init(tfm); } static struct crypto_template eseqiv_tmpl; @@ -220,7 +199,7 @@ static struct crypto_instance *eseqiv_alloc(struct rtattr **tb) if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize) goto free_inst; - inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt; inst->alg.cra_init = eseqiv_init; inst->alg.cra_exit = skcipher_geniv_exit; diff --git a/crypto/krng.c b/crypto/krng.c deleted file mode 100644 index a2d2b72fc135b4..00000000000000 --- a/crypto/krng.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * RNG implementation using standard kernel RNG. - * - * Copyright (c) 2008 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * any later version. - * - */ - -#include -#include -#include -#include -#include - -static int krng_get_random(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen) -{ - get_random_bytes(rdata, dlen); - return 0; -} - -static int krng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) -{ - return 0; -} - -static struct crypto_alg krng_alg = { - .cra_name = "stdrng", - .cra_driver_name = "krng", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_RNG, - .cra_ctxsize = 0, - .cra_type = &crypto_rng_type, - .cra_module = THIS_MODULE, - .cra_u = { - .rng = { - .rng_make_random = krng_get_random, - .rng_reset = krng_reset, - .seedsize = 0, - } - } -}; - - -/* Module initalization */ -static int __init krng_mod_init(void) -{ - return crypto_register_alg(&krng_alg); -} - -static void __exit krng_mod_fini(void) -{ - crypto_unregister_alg(&krng_alg); - return; -} - -module_init(krng_mod_init); -module_exit(krng_mod_fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Kernel Random Number Generator"); -MODULE_ALIAS("stdrng"); diff --git a/crypto/seqiv.c b/crypto/seqiv.c index f2cba4ed6f256b..c7c7687eff7076 100644 --- a/crypto/seqiv.c +++ b/crypto/seqiv.c @@ -186,52 +186,6 @@ static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req) return err; } -static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err = 0; - - spin_lock_bh(&ctx->lock); - if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first) - goto unlock; - - crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_ablkcipher_ivsize(geniv)); - -unlock: - spin_unlock_bh(&ctx->lock); - - if (err) - return err; - - return seqiv_givencrypt(req); -} - -static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req) -{ - struct crypto_aead *geniv = aead_givcrypt_reqtfm(req); - struct seqiv_ctx *ctx = crypto_aead_ctx(geniv); - int err = 0; - - spin_lock_bh(&ctx->lock); - if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first) - goto unlock; - - crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_aead_ivsize(geniv)); - -unlock: - spin_unlock_bh(&ctx->lock); - - if (err) - return err; - - return seqiv_aead_givencrypt(req); -} - static int seqiv_init(struct crypto_tfm *tfm) { struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); @@ -241,7 +195,9 @@ static int seqiv_init(struct crypto_tfm *tfm) tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); - return skcipher_geniv_init(tfm); + return crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_ablkcipher_ivsize(geniv)) ?: + skcipher_geniv_init(tfm); } static int seqiv_aead_init(struct crypto_tfm *tfm) @@ -253,7 +209,9 @@ static int seqiv_aead_init(struct crypto_tfm *tfm) tfm->crt_aead.reqsize = sizeof(struct aead_request); - return aead_geniv_init(tfm); + return crypto_rng_get_bytes(crypto_default_rng, ctx->salt, + crypto_aead_ivsize(geniv)) ?: + aead_geniv_init(tfm); } static struct crypto_template seqiv_tmpl; @@ -267,7 +225,7 @@ static struct crypto_instance *seqiv_ablkcipher_alloc(struct rtattr **tb) if (IS_ERR(inst)) goto out; - inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first; + inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt; inst->alg.cra_init = seqiv_init; inst->alg.cra_exit = skcipher_geniv_exit; @@ -287,7 +245,7 @@ static struct crypto_instance *seqiv_aead_alloc(struct rtattr **tb) if (IS_ERR(inst)) goto out; - inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt_first; + inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt; inst->alg.cra_init = seqiv_aead_init; inst->alg.cra_exit = aead_geniv_exit; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9260905fdefe73..2469724f75de68 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2329,7 +2329,7 @@ static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) int low, high, remaining; unsigned int rover; - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(&init_net, &low, &high); remaining = (high - low) + 1; rover = net_random() % remaining + low; retry: diff --git a/drivers/of/base.c b/drivers/of/base.c index f1fa838522f148..00ada61451ccd9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -332,6 +332,23 @@ struct property *of_find_property(const struct device_node *np, } EXPORT_SYMBOL(of_find_property); +struct device_node *__of_find_all_nodes(struct device_node *prev) +{ + struct device_node *np; + if (!prev) { + np = of_allnodes; + } else if (prev->child) { + np = prev->child; + } else { + /* Walk back up looking for a sibling, or the end of the structure */ + np = prev; + while (np->parent && !np->sibling) + np = np->parent; + np = np->sibling; /* Might be null at the end of the tree */ + } + return np; +} + /** * of_find_all_nodes - Get next node in global list * @prev: Previous node or NULL to start iteration @@ -346,10 +363,8 @@ struct device_node *of_find_all_nodes(struct device_node *prev) unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = prev ? prev->allnext : of_allnodes; - for (; np != NULL; np = np->allnext) - if (of_node_get(np)) - break; + np = __of_find_all_nodes(prev); + of_node_get(np); of_node_put(prev); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; @@ -621,11 +636,11 @@ EXPORT_SYMBOL(of_get_child_by_name); */ struct device_node *of_find_node_by_path(const char *path) { - struct device_node *np = of_allnodes; + struct device_node *np; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - for (; np; np = np->allnext) { + for_each_of_allnodes(np) { if (np->full_name && (of_node_cmp(np->full_name, path) == 0) && of_node_get(np)) break; @@ -653,8 +668,7 @@ struct device_node *of_find_node_by_name(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) + for_each_of_allnodes_from(from, np) if (np->name && (of_node_cmp(np->name, name) == 0) && of_node_get(np)) break; @@ -683,8 +697,7 @@ struct device_node *of_find_node_by_type(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) + for_each_of_allnodes_from(from, np) if (np->type && (of_node_cmp(np->type, type) == 0) && of_node_get(np)) break; @@ -715,8 +728,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) { if (type && !(np->type && (of_node_cmp(np->type, type) == 0))) continue; @@ -750,8 +762,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) { for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, prop_name) == 0) { of_node_get(np); @@ -836,8 +847,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, *match = NULL; raw_spin_lock_irqsave(&devtree_lock, flags); - np = from ? from->allnext : of_allnodes; - for (; np; np = np->allnext) { + for_each_of_allnodes_from(from, np) { m = __of_match_node(matches, np); if (m && of_node_get(np)) { if (match) @@ -891,7 +901,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); - for (np = of_allnodes; np; np = np->allnext) + for_each_of_allnodes(np) if (np->phandle == handle) break; of_node_get(np); @@ -1658,9 +1668,7 @@ int of_attach_node(struct device_node *np) raw_spin_lock_irqsave(&devtree_lock, flags); np->sibling = np->parent->child; - np->allnext = of_allnodes; np->parent->child = np; - of_allnodes = np; raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_add(np); @@ -1710,17 +1718,6 @@ int of_detach_node(struct device_node *np) return rc; } - if (of_allnodes == np) - of_allnodes = np->allnext; - else { - struct device_node *prev; - for (prev = of_allnodes; - prev->allnext != np; - prev = prev->allnext) - ; - prev->allnext = np->allnext; - } - if (parent->child == np) parent->child = np->sibling; else { diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index fa82c003bc324b..ae4626f642083a 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -270,7 +270,7 @@ #define IPR_RUNTIME_RESET 0x40000000 #define IPR_IPL_INIT_MIN_STAGE_TIME 5 -#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15 +#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 30 #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 #define IPR_IPL_INIT_STAGE_MASK 0xff000000 diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ffaa7f3d53e512..9a3906af283c3c 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1620,6 +1620,7 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) int usb_hcd_unlink_urb (struct urb *urb, int status) { struct usb_hcd *hcd; + struct usb_device *udev = urb->dev; int retval = -EIDRM; unsigned long flags; @@ -1631,20 +1632,19 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) spin_lock_irqsave(&hcd_urb_unlink_lock, flags); if (atomic_read(&urb->use_count) > 0) { retval = 0; - usb_get_dev(urb->dev); + usb_get_dev(udev); } spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); if (retval == 0) { hcd = bus_to_hcd(urb->dev->bus); retval = unlink1(hcd, urb, status); - usb_put_dev(urb->dev); + if (retval == 0) + retval = -EINPROGRESS; + else if (retval != -EIDRM && retval != -EBUSY) + dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", + urb, retval); + usb_put_dev(udev); } - - if (retval == 0) - retval = -EINPROGRESS; - else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&urb->dev->dev, "hcd_unlink_urb %p fail %d\n", - urb, retval); return retval; } diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index e78af3a2abec0a..3ef7f932e809f5 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -662,6 +662,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, BUG_ON(end < lblk); + if ((status & EXTENT_STATUS_DELAYED) && + (status & EXTENT_STATUS_WRITTEN)) { + ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as " + " delayed and written which can potentially " + " cause data loss.\n", lblk, len); + WARN_ON(1); + } + newes.es_lblk = lblk; newes.es_len = len; ext4_es_store_pblock_status(&newes, pblk, status); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6553376eb365a7..d1c9937c0cdecb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -539,6 +539,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && + !(status & EXTENT_STATUS_WRITTEN) && ext4_find_delalloc_range(inode, map->m_lblk, map->m_lblk + map->m_len - 1)) status |= EXTENT_STATUS_DELAYED; @@ -653,6 +654,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && + !(status & EXTENT_STATUS_WRITTEN) && ext4_find_delalloc_range(inode, map->m_lblk, map->m_lblk + map->m_len - 1)) status |= EXTENT_STATUS_DELAYED; diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 54aab3339b6b3c..517a562739c826 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -233,7 +233,7 @@ static void fscache_release_retrieval_op(struct fscache_operation *_op) _enter("{OP%x}", op->op.debug_id); - ASSERTCMP(op->n_pages, ==, 0); + ASSERTCMP(atomic_read(&op->n_pages), ==, 0); fscache_hist(fscache_retrieval_histogram, op->start_time); if (op->context) @@ -310,7 +310,7 @@ static void fscache_do_cancel_retrieval(struct fscache_operation *_op) struct fscache_retrieval *op = container_of(_op, struct fscache_retrieval, op); - op->n_pages = 0; + atomic_set(&op->n_pages, 0); } /* @@ -399,7 +399,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, _leave(" = -ENOMEM"); return -ENOMEM; } - op->n_pages = 1; + atomic_set(&op->n_pages, 1); spin_lock(&cookie->lock); @@ -525,7 +525,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, op = fscache_alloc_retrieval(mapping, end_io_func, context); if (!op) return -ENOMEM; - op->n_pages = *nr_pages; + atomic_set(&op->n_pages, *nr_pages); spin_lock(&cookie->lock); @@ -634,7 +634,7 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, op = fscache_alloc_retrieval(page->mapping, NULL, NULL); if (!op) return -ENOMEM; - op->n_pages = 1; + atomic_set(&op->n_pages, 1); spin_lock(&cookie->lock); diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index c836b55c64f503..eee9757d2ef7e1 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -2345,6 +2345,7 @@ static void nfs4_state_manager(struct nfs_client *clp) status = nfs4_check_lease(clp); if (status < 0) goto out_error; + continue; } if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) { diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index 696c7fd7f49cec..c81b7e8df9a02c 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -29,8 +29,9 @@ #define CEPH_OPT_NOSHARE (1<<1) /* don't share client with other sbs */ #define CEPH_OPT_MYIP (1<<2) /* specified my ip */ #define CEPH_OPT_NOCRC (1<<3) /* no data crc on writes */ +#define CEPH_OPT_TCP_NODELAY (1<<5) /* TCP_NODELAY on TCP sockets */ -#define CEPH_OPT_DEFAULT (0) +#define CEPH_OPT_DEFAULT (CEPH_OPT_TCP_NODELAY) #define ceph_set_opt(client, opt) \ (client)->options->flags |= CEPH_OPT_##opt; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 08840502c99ea9..27a33858369ea8 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -52,6 +52,7 @@ struct ceph_messenger { atomic_t stopping; bool nocrc; + bool tcp_nodelay; /* * the global_seq counts connections i (attempt to) initiate @@ -257,7 +258,8 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, struct ceph_entity_addr *myaddr, u64 supported_features, u64 required_features, - bool nocrc); + bool nocrc, + bool tcp_nodelay); extern void ceph_con_init(struct ceph_connection *con, void *private, const struct ceph_connection_operations *ops, diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 5dfa0aa216b66f..525617c1d9f7e6 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -150,7 +150,7 @@ struct fscache_retrieval { void *context; /* netfs read context (pinned) */ struct list_head to_do; /* list of things to be done by the backend */ unsigned long start_time; /* time at which retrieval started */ - unsigned n_pages; /* number of pages to be retrieved */ + atomic_t n_pages; /* number of pages to be retrieved */ }; typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op, @@ -194,15 +194,14 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op) static inline void fscache_retrieval_complete(struct fscache_retrieval *op, int n_pages) { - op->n_pages -= n_pages; - if (op->n_pages <= 0) + atomic_sub(n_pages, &op->n_pages); + if (atomic_read(&op->n_pages) <= 0) fscache_op_complete(&op->op, true); } /** * fscache_put_retrieval - Drop a reference to a retrieval operation * @op: The retrieval operation affected - * @n_pages: The number of pages to account for * * Drop a reference to a retrieval operation. */ diff --git a/include/linux/nmi.h b/include/linux/nmi.h index 6a45fb583ff145..1806dba1462f68 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -24,6 +24,19 @@ static inline void touch_nmi_watchdog(void) } #endif +#if defined(CONFIG_HARDLOCKUP_DETECTOR) +extern void watchdog_enable_hardlockup_detector(bool val); +extern bool watchdog_hardlockup_detector_is_enabled(void); +#else +static inline void watchdog_enable_hardlockup_detector(bool val) +{ +} +static inline bool watchdog_hardlockup_detector_is_enabled(void) +{ + return true; +} +#endif + /* * Create trigger_all_cpu_backtrace() out of the arch-provided * base function. Return whether such support was available, diff --git a/include/linux/of.h b/include/linux/of.h index 768a2bb3829568..b94ec0c35402fc 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -139,6 +139,7 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag) set_bit(flag, &n->_flags); } +extern struct device_node *__of_find_all_nodes(struct device_node *prev); extern struct device_node *of_find_all_nodes(struct device_node *prev); /* @@ -190,8 +191,9 @@ static inline const char *of_node_full_name(const struct device_node *np) return np ? np->full_name : ""; } -#define for_each_of_allnodes(dn) \ - for (dn = of_allnodes; dn; dn = dn->allnext) +#define for_each_of_allnodes_from(from, dn) \ + for (dn = __of_find_all_nodes(from); dn; dn = __of_find_all_nodes(dn)) +#define for_each_of_allnodes(dn) for_each_of_allnodes_from(NULL, dn) extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); #define for_each_node_by_name(dn, name) \ diff --git a/include/net/ip.h b/include/net/ip.h index 0751f2e44f3770..cb82ef9cbbe52f 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -220,11 +220,7 @@ static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ]) } } -extern struct local_ports { - seqlock_t lock; - int range[2]; -} sysctl_local_ports; -extern void inet_get_local_port_range(int *low, int *high); +extern void inet_get_local_port_range(struct net *net, int *low, int *high); extern unsigned long *sysctl_local_reserved_ports; static inline int inet_is_reserved_local_port(int port) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 385ac027c6022e..6e98cac7ce7da7 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -129,6 +129,8 @@ struct net { RH_KABI_EXTEND(atomic_t fnhe_genid) RH_KABI_EXTEND(int sysctl_ip_no_pmtu_disc) RH_KABI_EXTEND(int sysctl_ip_fwd_use_pmtu) + /* upstream has this as part of netns_ipv4 */ + RH_KABI_EXTEND(struct local_ports ipv4_sysctl_local_ports) }; /* diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 86372ae0ee840a..31158f38a98001 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -47,8 +47,8 @@ enum nf_ct_ext_id { /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { struct rcu_head rcu; - u8 offset[NF_CT_EXT_NUM]; - u8 len; + u16 offset[NF_CT_EXT_NUM]; + u16 len; char data[0]; }; diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2ba9de89e8ec77..9c541fccc7eb0e 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -16,6 +16,11 @@ struct hlist_head; struct fib_table; struct sock; +struct local_ports { + seqlock_t lock; + int range[2]; +}; + struct netns_ipv4 { #ifdef CONFIG_SYSCTL struct ctl_table_header *forw_hdr; diff --git a/include/net/udp.h b/include/net/udp.h index bba909b90a944a..da73ce1367a208 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -194,14 +194,14 @@ extern int udp_lib_get_port(struct sock *sk, unsigned short snum, int (*)(const struct sock *,const struct sock *), unsigned int hash2_nulladdr); -static inline __be16 udp_flow_src_port(struct net __attribute__((unused)) *net, struct sk_buff *skb, +static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, int min, int max, bool use_eth) { u32 hash; if (min >= max) { /* Use default range */ - inet_get_local_port_range(&min, &max); + inet_get_local_port_range(net, &min, &max); } hash = skb_get_hash(skb); diff --git a/kernel/module.c b/kernel/module.c index 04eeb4cfa19b6a..336b40bdf589b3 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3438,6 +3438,9 @@ static int load_module(struct load_info *info, const char __user *uargs, module_bug_cleanup(mod); mutex_unlock(&module_mutex); + blocking_notifier_call_chain(&module_notify_list, + MODULE_STATE_GOING, mod); + /* we can't deallocate the module until we clear memory protection */ unset_module_init_ro_nx(mod); unset_module_core_ro_nx(mod); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 51c4f34d258ea3..69146dcbc82fca 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -56,6 +56,25 @@ static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); static int hardlockup_panic = CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; +static bool hardlockup_detector_enabled = true; +/* + * We may not want to enable hard lockup detection by default in all cases, + * for example when running the kernel as a guest on a hypervisor. In these + * cases this function can be called to disable hard lockup detection. This + * function should only be executed once by the boot processor before the + * kernel command line parameters are parsed, because otherwise it is not + * possible to override this in hardlockup_panic_setup(). + */ +void watchdog_enable_hardlockup_detector(bool val) +{ + hardlockup_detector_enabled = val; +} + +bool watchdog_hardlockup_detector_is_enabled(void) +{ + return hardlockup_detector_enabled; +} + static int __init hardlockup_panic_setup(char *str) { if (!strncmp(str, "panic", 5)) @@ -64,6 +83,14 @@ static int __init hardlockup_panic_setup(char *str) hardlockup_panic = 0; else if (!strncmp(str, "0", 1)) watchdog_user_enabled = 0; + else if (!strncmp(str, "1", 1) || !strncmp(str, "2", 1)) { + /* + * Setting 'nmi_watchdog=1' or 'nmi_watchdog=2' (legacy option) + * has the same effect. + */ + watchdog_user_enabled = 1; + watchdog_enable_hardlockup_detector(true); + } return 1; } __setup("nmi_watchdog=", hardlockup_panic_setup); @@ -408,6 +435,15 @@ static int watchdog_nmi_enable(unsigned int cpu) struct perf_event_attr *wd_attr; struct perf_event *event = per_cpu(watchdog_ev, cpu); + /* + * Some kernels need to default hard lockup detection to + * 'disabled', for example a guest on a hypervisor. + */ + if (!watchdog_hardlockup_detector_is_enabled()) { + event = ERR_PTR(-ENOENT); + goto handle_err; + } + /* is it already setup and enabled? */ if (event && event->state > PERF_EVENT_STATE_OFF) goto out; @@ -422,6 +458,7 @@ static int watchdog_nmi_enable(unsigned int cpu) /* Try to register using hardware perf events */ event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL); +handle_err: /* save cpu0 error for future comparision */ if (cpu == 0 && IS_ERR(event)) cpu0_err = PTR_ERR(event); @@ -468,7 +505,10 @@ static void watchdog_nmi_disable(unsigned int cpu) /* should be in cleanup, but blocks oprofile */ perf_event_release_kernel(event); } - return; + if (cpu == 0) { + /* watchdog_nmi_enable() expects this to be zero initially. */ + cpu0_err = 0; + } } #else static int watchdog_nmi_enable(unsigned int cpu) { return 0; } @@ -486,7 +526,51 @@ static struct smp_hotplug_thread watchdog_threads = { .unpark = watchdog_enable, }; -static int watchdog_enable_all_cpus(void) +static void restart_watchdog_hrtimer(void *info) +{ + struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + int ret; + + /* + * No need to cancel and restart hrtimer if it is currently executing + * because it will reprogram itself with the new period now. + * We should never see it unqueued here because we are running per-cpu + * with interrupts disabled. + */ + ret = hrtimer_try_to_cancel(hrtimer); + if (ret == 1) + hrtimer_start(hrtimer, ns_to_ktime(sample_period), + HRTIMER_MODE_REL_PINNED); +} + +static void update_timers(int cpu) +{ + /* + * Make sure that perf event counter will adopt to a new + * sampling period. Updating the sampling period directly would + * be much nicer but we do not have an API for that now so + * let's use a big hammer. + * Hrtimer will adopt the new period on the next tick but this + * might be late already so we have to restart the timer as well. + */ + watchdog_nmi_disable(cpu); + smp_call_function_single(cpu, restart_watchdog_hrtimer, NULL, 1); + watchdog_nmi_enable(cpu); +} + +static void update_timers_all_cpus(void) +{ + int cpu; + + get_online_cpus(); + preempt_disable(); + for_each_online_cpu(cpu) + update_timers(cpu); + preempt_enable(); + put_online_cpus(); +} + +static int watchdog_enable_all_cpus(bool sample_period_changed) { int err = 0; @@ -496,6 +580,8 @@ static int watchdog_enable_all_cpus(void) pr_err("Failed to create watchdog threads, disabled\n"); else watchdog_running = 1; + } else if (sample_period_changed) { + update_timers_all_cpus(); } return err; @@ -520,13 +606,17 @@ int proc_dowatchdog(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int err, old_thresh, old_enabled; + bool old_hardlockup; + static DEFINE_MUTEX(watchdog_proc_mutex); + mutex_lock(&watchdog_proc_mutex); old_thresh = ACCESS_ONCE(watchdog_thresh); old_enabled = ACCESS_ONCE(watchdog_user_enabled); + old_hardlockup = watchdog_hardlockup_detector_is_enabled(); err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (err || !write) - return err; + goto out; set_sample_period(); /* @@ -534,17 +624,25 @@ int proc_dowatchdog(struct ctl_table *table, int write, * disabled. The 'watchdog_running' variable check in * watchdog_*_all_cpus() function takes care of this. */ - if (watchdog_user_enabled && watchdog_thresh) - err = watchdog_enable_all_cpus(); - else + if (watchdog_user_enabled && watchdog_thresh) { + /* + * Prevent a change in watchdog_thresh accidentally overriding + * the enablement of the hardlockup detector. + */ + if (watchdog_user_enabled != old_enabled) + watchdog_enable_hardlockup_detector(true); + err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh); + } else watchdog_disable_all_cpus(); /* Restore old values on failure */ if (err) { watchdog_thresh = old_thresh; watchdog_user_enabled = old_enabled; + watchdog_enable_hardlockup_detector(old_hardlockup); } - +out: + mutex_unlock(&watchdog_proc_mutex); return err; } #endif /* CONFIG_SYSCTL */ @@ -554,5 +652,5 @@ void __init lockup_detector_init(void) set_sample_period(); if (watchdog_user_enabled) - watchdog_enable_all_cpus(); + watchdog_enable_all_cpus(false); } diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 58fbfe134f9329..fa0e3fd8832f55 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -245,6 +245,8 @@ enum { Opt_noshare, Opt_crc, Opt_nocrc, + Opt_tcp_nodelay, + Opt_notcp_nodelay, }; static match_table_t opt_tokens = { @@ -263,6 +265,8 @@ static match_table_t opt_tokens = { {Opt_noshare, "noshare"}, {Opt_crc, "crc"}, {Opt_nocrc, "nocrc"}, + {Opt_tcp_nodelay, "tcp_nodelay"}, + {Opt_notcp_nodelay, "notcp_nodelay"}, {-1, NULL} }; @@ -462,6 +466,13 @@ ceph_parse_options(char *options, const char *dev_name, opt->flags |= CEPH_OPT_NOCRC; break; + case Opt_tcp_nodelay: + opt->flags |= CEPH_OPT_TCP_NODELAY; + break; + case Opt_notcp_nodelay: + opt->flags &= ~CEPH_OPT_TCP_NODELAY; + break; + default: BUG_ON(token); } @@ -513,10 +524,12 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, /* msgr */ if (ceph_test_opt(client, MYIP)) myaddr = &client->options->my_addr; + ceph_messenger_init(&client->msgr, myaddr, client->supported_features, client->required_features, - ceph_test_opt(client, NOCRC)); + ceph_test_opt(client, NOCRC), + ceph_test_opt(client, TCP_NODELAY)); /* subsystems */ err = ceph_monc_init(&client->monc, client); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ccc54158a2201a..224e46e1055a05 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -507,6 +507,16 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } + if (con->msgr->tcp_nodelay) { + int optval = 1; + + ret = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, + (char *)&optval, sizeof(optval)); + if (ret) + pr_err("kernel_setsockopt(TCP_NODELAY) failed: %d", + ret); + } + sk_set_memalloc(sock->sk); con->sock = sock; @@ -2898,7 +2908,8 @@ void ceph_messenger_init(struct ceph_messenger *msgr, struct ceph_entity_addr *myaddr, u64 supported_features, u64 required_features, - bool nocrc) + bool nocrc, + bool tcp_nodelay) { msgr->supported_features = supported_features; msgr->required_features = required_features; @@ -2913,6 +2924,7 @@ void ceph_messenger_init(struct ceph_messenger *msgr, get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce)); encode_my_addr(msgr); msgr->nocrc = nocrc; + msgr->tcp_nodelay = tcp_nodelay; atomic_set(&msgr->stopping, 0); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 0b81fb520a6d07..a52addd1ee71c6 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -1006,14 +1006,24 @@ static void put_osd(struct ceph_osd *osd) */ static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) { - dout("__remove_osd %p\n", osd); + dout("%s %p osd%d\n", __func__, osd, osd->o_osd); WARN_ON(!list_empty(&osd->o_requests)); WARN_ON(!list_empty(&osd->o_linger_requests)); - rb_erase(&osd->o_node, &osdc->osds); list_del_init(&osd->o_osd_lru); - ceph_con_close(&osd->o_con); - put_osd(osd); + rb_erase(&osd->o_node, &osdc->osds); + RB_CLEAR_NODE(&osd->o_node); +} + +static void remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) +{ + dout("%s %p osd%d\n", __func__, osd, osd->o_osd); + + if (!RB_EMPTY_NODE(&osd->o_node)) { + ceph_con_close(&osd->o_con); + __remove_osd(osdc, osd); + put_osd(osd); + } } static void remove_all_osds(struct ceph_osd_client *osdc) @@ -1023,7 +1033,7 @@ static void remove_all_osds(struct ceph_osd_client *osdc) while (!RB_EMPTY_ROOT(&osdc->osds)) { struct ceph_osd *osd = rb_entry(rb_first(&osdc->osds), struct ceph_osd, o_node); - __remove_osd(osdc, osd); + remove_osd(osdc, osd); } mutex_unlock(&osdc->request_mutex); } @@ -1064,7 +1074,7 @@ static void remove_old_osds(struct ceph_osd_client *osdc) list_for_each_entry_safe(osd, nosd, &osdc->osd_lru, o_osd_lru) { if (time_before(jiffies, osd->lru_ttl)) break; - __remove_osd(osdc, osd); + remove_osd(osdc, osd); } mutex_unlock(&osdc->request_mutex); } @@ -1079,8 +1089,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) dout("__reset_osd %p osd%d\n", osd, osd->o_osd); if (list_empty(&osd->o_requests) && list_empty(&osd->o_linger_requests)) { - __remove_osd(osdc, osd); - + remove_osd(osdc, osd); return -ENODEV; } @@ -1884,6 +1893,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) { struct rb_node *p, *n; + dout("%s %p\n", __func__, osdc); for (p = rb_first(&osdc->osds); p; p = n) { struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 07622a4e3fa437..57bfc501a7f0f2 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -29,27 +29,19 @@ const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n"; EXPORT_SYMBOL(inet_csk_timer_bug_msg); #endif -/* - * This struct holds the first and last local port number. - */ -struct local_ports sysctl_local_ports __read_mostly = { - .lock = __SEQLOCK_UNLOCKED(sysctl_local_ports.lock), - .range = { 32768, 61000 }, -}; - unsigned long *sysctl_local_reserved_ports; EXPORT_SYMBOL(sysctl_local_reserved_ports); -void inet_get_local_port_range(int *low, int *high) +void inet_get_local_port_range(struct net *net, int *low, int *high) { unsigned int seq; do { - seq = read_seqbegin(&sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4_sysctl_local_ports.lock); - *low = sysctl_local_ports.range[0]; - *high = sysctl_local_ports.range[1]; - } while (read_seqretry(&sysctl_local_ports.lock, seq)); + *low = net->ipv4_sysctl_local_ports.range[0]; + *high = net->ipv4_sysctl_local_ports.range[1]; + } while (read_seqretry(&net->ipv4_sysctl_local_ports.lock, seq)); } EXPORT_SYMBOL(inet_get_local_port_range); @@ -115,7 +107,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) int remaining, rover, low, high; again: - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(net, &low, &high); remaining = (high - low) + 1; smallest_rover = rover = net_random() % remaining + low; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 55d6df700a4224..9900059c98092f 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -469,7 +469,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, u32 offset = hint + port_offset; struct inet_timewait_sock *tw = NULL; - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(net, &low, &high); remaining = (high - low) + 1; local_bh_disable(); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index fd81a2b7bc9168..e8952760c7ba90 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -139,6 +139,7 @@ static void ping_v4_unhash(struct sock *sk) if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); + sk_nulls_node_init(&sk->sk_nulls_node); sock_put(sk); isk->inet_num = 0; isk->inet_sport = 0; @@ -192,11 +193,11 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, unsigned int seq; do { - seq = read_seqbegin(&sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4_sysctl_local_ports.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&sysctl_local_ports.lock, seq)); + } while (read_seqretry(&net->ipv4_sysctl_local_ports.lock, seq)); } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index b59465fb948e65..1134ef4a28e542 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -43,12 +43,12 @@ static int ip_ping_group_range_min[] = { 0, 0 }; static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; /* Update system visible IP port range */ -static void set_local_port_range(int range[2]) +static void set_local_port_range(struct net *net, int range[2]) { - write_seqlock(&sysctl_local_ports.lock); - sysctl_local_ports.range[0] = range[0]; - sysctl_local_ports.range[1] = range[1]; - write_sequnlock(&sysctl_local_ports.lock); + write_seqlock(&net->ipv4_sysctl_local_ports.lock); + net->ipv4_sysctl_local_ports.range[0] = range[0]; + net->ipv4_sysctl_local_ports.range[1] = range[1]; + write_sequnlock(&net->ipv4_sysctl_local_ports.lock); } /* Validate changes from /proc interface. */ @@ -56,6 +56,8 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { + struct net *net = + container_of(table->data, struct net, ipv4_sysctl_local_ports.range); int ret; int range[2]; struct ctl_table tmp = { @@ -66,14 +68,15 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, .extra2 = &ip_local_port_range_max, }; - inet_get_local_port_range(range, range + 1); + inet_get_local_port_range(net, &range[0], &range[1]); + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); if (write && ret == 0) { if (range[1] < range[0]) ret = -EINVAL; else - set_local_port_range(range); + set_local_port_range(net, range); } return ret; @@ -83,23 +86,27 @@ static int ipv4_local_port_range(struct ctl_table *table, int write, static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) { kgid_t *data = table->data; + struct net *net = + container_of(table->data, struct net, ipv4.sysctl_ping_group_range); unsigned int seq; do { - seq = read_seqbegin(&sysctl_local_ports.lock); + seq = read_seqbegin(&net->ipv4_sysctl_local_ports.lock); *low = data[0]; *high = data[1]; - } while (read_seqretry(&sysctl_local_ports.lock, seq)); + } while (read_seqretry(&net->ipv4_sysctl_local_ports.lock, seq)); } /* Update system visible IP port range */ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) { kgid_t *data = table->data; - write_seqlock(&sysctl_local_ports.lock); + struct net *net = + container_of(table->data, struct net, ipv4.sysctl_ping_group_range); + write_seqlock(&net->ipv4_sysctl_local_ports.lock); data[0] = low; data[1] = high; - write_sequnlock(&sysctl_local_ports.lock); + write_sequnlock(&net->ipv4_sysctl_local_ports.lock); } /* Validate changes from /proc interface. */ @@ -467,13 +474,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "ip_local_port_range", - .data = &sysctl_local_ports.range, - .maxlen = sizeof(sysctl_local_ports.range), - .mode = 0644, - .proc_handler = ipv4_local_port_range, - }, { .procname = "ip_local_reserved_ports", .data = NULL, /* initialized in sysctl_ipv4_init */ @@ -840,6 +840,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "ip_local_port_range", + .maxlen = sizeof(init_net.ipv4_sysctl_local_ports.range), + .data = &init_net.ipv4_sysctl_local_ports.range, + .mode = 0644, + .proc_handler = ipv4_local_port_range, + }, { .procname = "tcp_mem", .maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem), @@ -889,6 +896,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) &net->ipv4.sysctl_ping_group_range; table[7].data = &net->ipv4.sysctl_tcp_ecn; + table[8].data = + &net->ipv4_sysctl_local_ports.range; /* Don't export sysctls to unprivileged users */ if (net->user_ns != &init_user_ns) @@ -902,6 +911,13 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); + /* + * Set defaults for local port range + */ + seqlock_init(&net->ipv4_sysctl_local_ports.lock); + net->ipv4_sysctl_local_ports.range[0] = 32768; + net->ipv4_sysctl_local_ports.range[1] = 61000; + tcp_init_mem(net); net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index a66d0e6f3b8e91..c80ac5199f4ab2 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -220,7 +220,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, unsigned short first, last; DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(net, &low, &high); remaining = (high - low) + 1; rand = net_random(); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 72bd4506c52ee2..8da02219f4c001 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1191,7 +1191,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) if (rt) rt6_set_expires(rt, jiffies + (HZ * lifetime)); if (ra_msg->icmph.icmp6_hop_limit) { - in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; + /* Only set hop_limit on the interface if it is higher than + * the current hop_limit. + */ + if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) { + in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; + } else { + ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n"); + } if (rt) dst_metric_set(&rt->dst, RTAX_HOPLIMIT, ra_msg->icmph.icmp6_hop_limit); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3f52f2a398da54..6387a90acda7f2 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5927,7 +5927,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) int low, high, remaining, index; unsigned int rover; - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(sock_net(sk), &low, &high); remaining = (high - low) + 1; rover = net_random() % remaining + low; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 488ddeed9363db..e0b94ce4c4e62b 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -461,6 +461,8 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, if (args->flags & RPC_CLNT_CREATE_AUTOBIND) clnt->cl_autobind = 1; + if (args->flags & RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT) + clnt->cl_noretranstimeo = 1; if (args->flags & RPC_CLNT_CREATE_DISCRTRY) clnt->cl_discrtry = 1; if (!(args->flags & RPC_CLNT_CREATE_QUIET)) @@ -579,6 +581,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, /* Turn off autobind on clones */ new->cl_autobind = 0; new->cl_softrtry = clnt->cl_softrtry; + new->cl_noretranstimeo = clnt->cl_noretranstimeo; new->cl_discrtry = clnt->cl_discrtry; new->cl_chatty = clnt->cl_chatty; return new; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c2224018b96cbc..0f19ee84d6432b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3977,7 +3977,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in if (snum) { int low, high; - inet_get_local_port_range(&low, &high); + inet_get_local_port_range(sock_net(sk), &low, &high); if (snum < max(PROT_SOCK, low) || snum > high) { err = sel_netport_sid(sk->sk_protocol,