This is the start of the stable review cycle for the 3.4.20 release.
There are 171 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sat Nov 24 00:36:21 UTC 2012.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v3.0/stable-review/patch-3.4.20-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 3.4.20-rc1
Felipe Balbi <[email protected]>
Revert "serial: omap: fix software flow control"
Igor Murzov <[email protected]>
ACPI video: Ignore errors after _DOD evaluation.
Alex Elder <[email protected]>
ceph: avoid 32-bit page index overflow
Sage Weil <[email protected]>
libceph: check for invalid mapping
Yan, Zheng <[email protected]>
ceph: Fix oops when handling mdsmap that decreases max_mds
Sage Weil <[email protected]>
libceph: avoid NULL kref_put when osd reset races with alloc_msg
Alex Elder <[email protected]>
rbd: reset BACKOFF if unable to re-queue
Alex Elder <[email protected]>
libceph: only kunmap kmapped pages
Jim Schutt <[email protected]>
libceph: avoid truncation due to racing banners
Sage Weil <[email protected]>
libceph: delay debugfs initialization until we learn global_id
Sylvain Munaut <[email protected]>
libceph: fix crypto key null deref, memory leak
Sage Weil <[email protected]>
libceph: recheck con state after allocating incoming message
Sage Weil <[email protected]>
libceph: change ceph_con_in_msg_alloc convention to be less weird
Sage Weil <[email protected]>
libceph: avoid dropping con mutex before fault
Sage Weil <[email protected]>
libceph: verify state after retaking con lock after dispatch
Sage Weil <[email protected]>
libceph: revoke mon_client messages on session restart
Sage Weil <[email protected]>
libceph: fix handling of immediate socket connect failure
Sage Weil <[email protected]>
libceph: clear all flags on con_close
Sage Weil <[email protected]>
libceph: clean up con flags
Sage Weil <[email protected]>
libceph: replace connection state bits with states
Sage Weil <[email protected]>
libceph: drop unnecessary CLOSED check in socket state change callback
Sage Weil <[email protected]>
libceph: close socket directly from ceph_con_close()
Sage Weil <[email protected]>
libceph: drop gratuitous socket close calls in con_work
Sage Weil <[email protected]>
libceph: move ceph_con_send() closed check under the con mutex
Sage Weil <[email protected]>
libceph: move msgr clear_standby under con mutex protection
Sage Weil <[email protected]>
libceph: fix fault locking; close socket on lossy fault
Sage Weil <[email protected]>
libceph: reset connection retry on successfully negotiation
Sage Weil <[email protected]>
libceph: protect ceph_con_open() with mutex
Sage Weil <[email protected]>
libceph: (re)initialize bio_iter on start of message receive
Sage Weil <[email protected]>
libceph: resubmit linger ops when pg mapping changes
Sage Weil <[email protected]>
libceph: fix mutex coverage for ceph_con_close
Sage Weil <[email protected]>
libceph: report socket read/write error message
Guanjun He <[email protected]>
libceph: prevent the race of incoming work during teardown
Sage Weil <[email protected]>
libceph: initialize msgpool message types
Sage Weil <[email protected]>
libceph: allow sock transition from CONNECTING to CLOSED
Sage Weil <[email protected]>
libceph: initialize mon_client con only once
Sage Weil <[email protected]>
libceph: set peer name on con_open, not init
Alex Elder <[email protected]>
libceph: add some fine ASCII art
Alex Elder <[email protected]>
libceph: small changes to messenger.c
Alex Elder <[email protected]>
libceph: distinguish two phases of connect sequence
Alex Elder <[email protected]>
libceph: separate banner and connect writes
Alex Elder <[email protected]>
libceph: define and use an explicit CONNECTED state
Alex Elder <[email protected]>
libceph: clear NEGOTIATING when done
Alex Elder <[email protected]>
libceph: clear CONNECTING in ceph_con_close()
Alex Elder <[email protected]>
libceph: don't touch con state in con_close_socket()
Alex Elder <[email protected]>
libceph: just set SOCK_CLOSED when state changes
Alex Elder <[email protected]>
libceph: don't change socket state on sock event
Alex Elder <[email protected]>
libceph: SOCK_CLOSED is a flag, not a state
Alex Elder <[email protected]>
libceph: don't use bio_iter as a flag
Alex Elder <[email protected]>
libceph: move init of bio_iter
Alex Elder <[email protected]>
libceph: move init_bio_*() functions up
Alex Elder <[email protected]>
libceph: don't mark footer complete before it is
Alex Elder <[email protected]>
libceph: encapsulate advancing msg page
Alex Elder <[email protected]>
libceph: encapsulate out message data setup
Sage Weil <[email protected]>
libceph: drop ceph_con_get/put helpers and nref member
Sage Weil <[email protected]>
libceph: use con get/put methods
Dan Carpenter <[email protected]>
libceph: fix NULL dereference in reset_connection()
Sage Weil <[email protected]>
libceph: transition socket state prior to actual connect
Xi Wang <[email protected]>
libceph: fix overflow in osdmap_apply_incremental()
Xi Wang <[email protected]>
libceph: fix overflow in osdmap_decode()
Xi Wang <[email protected]>
libceph: fix overflow in __decode_pool_names()
Alex Elder <[email protected]>
libceph: make ceph_con_revoke_message() a msg op
Alex Elder <[email protected]>
libceph: make ceph_con_revoke() a msg operation
Alex Elder <[email protected]>
libceph: have messages take a connection reference
Alex Elder <[email protected]>
libceph: have messages point to their connection
Alex Elder <[email protected]>
libceph: tweak ceph_alloc_msg()
Alex Elder <[email protected]>
libceph: fully initialize connection in con_init()
Alex Elder <[email protected]>
libceph: init monitor connection when opening
Sage Weil <[email protected]>
libceph: drop connection refcounting for mon_client
Alex Elder <[email protected]>
libceph: embed ceph connection structure in mon_client
Alex Elder <[email protected]>
libceph: set CLOSED state bit in con_init
Alex Elder <[email protected]>
libceph: provide osd number when creating osd
Alex Elder <[email protected]>
libceph: start tracking connection socket state
Alex Elder <[email protected]>
libceph: start separating connection flags from state
Alex Elder <[email protected]>
libceph: embed ceph messenger structure in ceph_client
Alex Elder <[email protected]>
libceph: rename kvec_reset and kvec_add functions
Alex Elder <[email protected]>
libceph: rename socket callbacks
Alex Elder <[email protected]>
libceph: kill bad_proto ceph connection op
Alex Elder <[email protected]>
libceph: eliminate connection state "DEAD"
Yan, Zheng <[email protected]>
ceph: check PG_Private flag before accessing page->private
Yan, Zheng <[email protected]>
rbd: Fix ceph_snap_context size calculation
Josh Durgin <[email protected]>
rbd: store snapshot id instead of index
Josh Durgin <[email protected]>
rbd: protect read of snapshot sequence number
Alex Elder <[email protected]>
rbd: don't hold spinlock during messenger flush
Sage Weil <[email protected]>
libceph: fix messenger retry
Sage Weil <[email protected]>
libceph: flush msgr queue during mon_client shutdown
Yan, Zheng <[email protected]>
rbd: Clear ceph_msg->bio_iter for retransmitted message
Sage Weil <[email protected]>
libceph: use con get/put ops from osd_client
Alex Elder <[email protected]>
libceph: osd_client: don't drop reply reference too early
Sage Weil <[email protected]>
libceph: fix pg_temp updates
Sage Weil <[email protected]>
libceph: avoid unregistering osd request when not registered
Alex Elder <[email protected]>
ceph: add auth buf in prepare_write_connect()
Alex Elder <[email protected]>
ceph: rename prepare_connect_authorizer()
Alex Elder <[email protected]>
ceph: return pointer from prepare_connect_authorizer()
Alex Elder <[email protected]>
ceph: use info returned by get_authorizer
Alex Elder <[email protected]>
ceph: have get_authorizer methods return pointers
Alex Elder <[email protected]>
ceph: ensure auth ops are defined before use
Alex Elder <[email protected]>
ceph: messenger: reduce args to create_authorizer
Alex Elder <[email protected]>
ceph: define ceph_auth_handshake type
Alex Elder <[email protected]>
ceph: messenger: check return from get_authorizer
Alex Elder <[email protected]>
ceph: messenger: rework prepare_connect_authorizer()
Alex Elder <[email protected]>
ceph: messenger: check prepare_write_connect() result
Alex Elder <[email protected]>
ceph: don't set WRITE_PENDING too early
Alex Elder <[email protected]>
ceph: drop msgr argument from prepare_write_connect()
Alex Elder <[email protected]>
ceph: messenger: send banner in process_connect()
Alex Elder <[email protected]>
ceph: messenger: reset connection kvec caller
Alex Elder <[email protected]>
libceph: don't reset kvec in prepare_write_banner()
Alex Elder <[email protected]>
ceph: messenger: change read_partial() to take "end" arg
Alex Elder <[email protected]>
ceph: messenger: update "to" in read_partial() caller
Alex Elder <[email protected]>
ceph: messenger: use read_partial() in read_partial_message()
Alex Elder <[email protected]>
ceph: osd_client: fix endianness bug in osd_req_encode_op()
Sage Weil <[email protected]>
crush: fix memory leak when destroying tree buckets
Sage Weil <[email protected]>
crush: fix tree node weight lookup
Sage Weil <[email protected]>
crush: be more tolerant of nonsensical crush maps
Sage Weil <[email protected]>
crush: adjust local retry threshold
Sage Weil <[email protected]>
crush: clean up types, const-ness
Dave Jones <[email protected]>
selinux: fix sel_netnode_insert() suspicious rcu dereference
Jan Kara <[email protected]>
reiserfs: Protect reiserfs_quota_write() with write lock
Jan Kara <[email protected]>
reiserfs: Move quota calls out of write lock
Jan Kara <[email protected]>
reiserfs: Protect reiserfs_quota_on() with write lock
Jan Kara <[email protected]>
reiserfs: Fix lock ordering during remount
Bryan Schumaker <[email protected]>
NFS: Wait for session recovery to finish before returning
Daniel Vetter <[email protected]>
drm/i915: fix overlay on i830M
Martin Schwidefsky <[email protected]>
s390/signal: set correct address space control
Mirko Lindner <[email protected]>
sky2: Fix for interrupt handler
Tim Sally <[email protected]>
eCryptfs: check for eCryptfs cipher support at mount
Tyler Hicks <[email protected]>
eCryptfs: Copy up POSIX ACL and read-only flags from lower mount
Jan Safrata <[email protected]>
usb: use usb_serial_put in usb_serial_probe errors
Ulrich Weber <[email protected]>
netfilter: nf_nat: don't check for port change on ICMP tuples
Jozsef Kadlecsik <[email protected]>
netfilter: Mark SYN/ACK packets as invalid from original direction
Jozsef Kadlecsik <[email protected]>
netfilter: Validate the sequence number of dataless ACK packets as well
Nathan Walp <[email protected]>
r8169: allow multicast packets on sub-8168f chipset.
Cyril Brulebois <[email protected]>
r8169: Fix WoL on RTL8168d/8111d.
Mojiong Qiu <[email protected]>
xen/events: fix RCU warning, or Call idle notifier after irq_enter()
Michal Schmidt <[email protected]>
r8169: use unlimited DMA burst for TX
Hugh Dickins <[email protected]>
tmpfs: change final i_blocks BUG to WARNING
Tom Herbert <[email protected]>
net-rps: Fix brokeness causing OOO packets
Jiri Pirko <[email protected]>
net: correct check in dev_addr_del()
Hannes Frederic Sowa <[email protected]>
ipv6: setsockopt(IPIPPROTO_IPV6, IPV6_MINHOPCOUNT) forgot to set return value
Xi Wang <[email protected]>
ipv4: avoid undefined behavior in do_ip_setsockopt()
Andreas Schwab <[email protected]>
m68k: fix sigset_t accessor functions
Johannes Berg <[email protected]>
wireless: allow 40 MHz on world roaming channels 12/13
Michal Hocko <[email protected]>
memcg: oom: fix totalpages calculation for memory.swappiness==0
Zhao Yakui <[email protected]>
ttm: Clear the ttm page allocated from high memory zone correctly
Alex Deucher <[email protected]>
drm/radeon: fix logic error in atombios_encoders.c
Dan Williams <[email protected]>
USB: option: add Alcatel X220/X500D USB IDs
Dan Williams <[email protected]>
USB: option: add Novatel E362 and Dell Wireless 5800 USB IDs
Heiko Carstens <[email protected]>
s390/gup: add missing TASK_SIZE check to get_user_pages_fast()
Colin Cross <[email protected]>
Revert "Staging: Android alarm: IOCTL command encoding fix"
Artem Bityutskiy <[email protected]>
UBIFS: introduce categorized lprops counter
Artem Bityutskiy <[email protected]>
UBIFS: fix mounting problems after power cuts
Misael Lopez Cruz <[email protected]>
ASoC: dapm: Use card_list during DAPM shutdown
Eric Millbrandt <[email protected]>
ASoC: wm8978: pll incorrectly configured when codec is master
Takashi Iwai <[email protected]>
ALSA: hda - Add a missing quirk entry for iMac 9,1
Kailang Yang <[email protected]>
ALSA: hda - Add new codec ALC668 and ALC900 (default name ALC1150)
Takashi Iwai <[email protected]>
ALSA: hda - Fix invalid connections in VT1802 codec
Takashi Iwai <[email protected]>
ALSA: hda - Fix empty DAC filling in patch_via.c
Takashi Iwai <[email protected]>
ALSA: hda - Force to reset IEC958 status bits for AD codecs
Daniel J Blueman <[email protected]>
ALSA: HDA: Fix digital microphone on CS420x
Alexander Stein <[email protected]>
ALSA: hda: Cirrus: Fix coefficient index for beep configuration
Jacob Keller <[email protected]>
ptp: update adjfreq callback description
Jussi Kivilinna <[email protected]>
crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption
Jeff Layton <[email protected]>
cifs: fix potential buffer overrun in cifs.idmap handling code
Rusty Russell <[email protected]>
module: fix out-by-one error in kallsyms
Eric Paris <[email protected]>
fanotify: fix missing break
Huang Ying <[email protected]>
PCI/PM: Fix deadlock when unbinding device if parent in D3cold
Felix Fietkau <[email protected]>
mac80211: call skb_dequeue/ieee80211_free_txskb instead of __skb_queue_purge
Johannes Berg <[email protected]>
mac80211: don't send null data packet when not associated
Arik Nemtsov <[email protected]>
mac80211: sync acccess to tx_filtered/ps_tx_buf queues
Dave Chinner <[email protected]>
xfs: drop buffer io reference when a bad bio is built
Takamori Yamaguchi <[email protected]>
mm: bugfix: set current->reclaim_state to NULL while returning from kswapd()
-------------
Diffstat:
Documentation/cgroups/memory.txt | 4 +
Makefile | 4 +-
arch/arm/plat-omap/include/plat/omap-serial.h | 4 +-
arch/m68k/include/asm/signal.h | 6 +-
arch/s390/include/asm/compat.h | 2 +-
arch/s390/include/asm/ptrace.h | 4 +-
arch/s390/kernel/compat_signal.c | 14 +-
arch/s390/kernel/signal.c | 14 +-
arch/s390/mm/gup.c | 2 +-
crypto/cryptd.c | 11 +-
drivers/acpi/video.c | 11 +-
drivers/block/rbd.c | 37 +-
drivers/gpu/drm/i915/intel_overlay.c | 14 +-
drivers/gpu/drm/radeon/atombios_encoders.c | 2 +-
drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 +-
drivers/net/ethernet/marvell/sky2.c | 4 +-
drivers/net/ethernet/realtek/r8169.c | 7 +-
drivers/pci/bus.c | 3 -
drivers/pci/pcie/aer/aerdrv_core.c | 20 +-
drivers/staging/android/android_alarm.h | 4 +-
drivers/tty/serial/omap-serial.c | 12 +-
drivers/usb/serial/option.c | 9 +
drivers/usb/serial/usb-serial.c | 6 +-
drivers/xen/events.c | 2 +-
fs/ceph/addr.c | 32 +-
fs/ceph/debugfs.c | 1 +
fs/ceph/mds_client.c | 67 +-
fs/ceph/mds_client.h | 5 +-
fs/cifs/cifsacl.c | 49 +-
fs/ecryptfs/main.c | 23 +-
fs/nfs/nfs4proc.c | 3 +-
fs/notify/fanotify/fanotify.c | 1 +
fs/reiserfs/inode.c | 10 +-
fs/reiserfs/stree.c | 4 +
fs/reiserfs/super.c | 60 +-
fs/ubifs/find.c | 12 +-
fs/ubifs/lprops.c | 6 +
fs/ubifs/ubifs.h | 3 +
fs/xfs/xfs_buf.c | 14 +-
include/linux/ceph/auth.h | 12 +-
include/linux/ceph/libceph.h | 2 +-
include/linux/ceph/messenger.h | 76 +-
include/linux/ceph/mon_client.h | 2 +-
include/linux/ceph/msgpool.h | 3 +-
include/linux/ceph/osd_client.h | 13 +-
include/linux/ceph/osdmap.h | 6 +-
include/linux/crush/crush.h | 7 +-
include/linux/crush/mapper.h | 6 +-
include/linux/ptp_clock_kernel.h | 3 +-
kernel/module.c | 27 +-
mm/memcontrol.c | 21 +-
mm/shmem.c | 2 +-
mm/vmscan.c | 2 +
net/ceph/auth_none.c | 15 +-
net/ceph/auth_x.c | 15 +-
net/ceph/ceph_common.c | 28 +-
net/ceph/crush/crush.c | 14 +-
net/ceph/crush/mapper.c | 66 +-
net/ceph/crypto.c | 1 +
net/ceph/crypto.h | 3 +-
net/ceph/debugfs.c | 4 +
net/ceph/messenger.c | 1103 +++++++++++++++----------
net/ceph/mon_client.c | 135 ++-
net/ceph/msgpool.c | 7 +-
net/ceph/osd_client.c | 175 ++--
net/ceph/osdmap.c | 44 +-
net/core/dev.c | 4 +-
net/core/dev_addr_lists.c | 3 +-
net/ipv4/ip_sockglue.c | 35 +-
net/ipv4/netfilter/nf_nat_standalone.c | 6 +-
net/ipv6/ipv6_sockglue.c | 1 +
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/sta_info.c | 11 +-
net/mac80211/status.c | 9 +
net/mac80211/tx.c | 9 +-
net/mac80211/util.c | 2 +
net/netfilter/nf_conntrack_proto_tcp.c | 29 +-
net/wireless/reg.c | 5 +-
security/selinux/netnode.c | 3 +-
sound/pci/hda/patch_analog.c | 1 +
sound/pci/hda/patch_cirrus.c | 16 +-
sound/pci/hda/patch_realtek.c | 3 +
sound/pci/hda/patch_via.c | 25 +-
sound/soc/codecs/wm8978.c | 2 +-
sound/soc/soc-dapm.c | 2 +-
85 files changed, 1506 insertions(+), 945 deletions(-)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d50b409fb8698571d8209e5adfe122e287e31290)
Initialize the type field for messages in a msgpool. The caller was doing
this for osd ops, but not for the reply messages.
Reported-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/msgpool.h | 3 ++-
net/ceph/msgpool.c | 7 ++++---
net/ceph/osd_client.c | 7 ++++---
3 files changed, 10 insertions(+), 7 deletions(-)
--- a/include/linux/ceph/msgpool.h
+++ b/include/linux/ceph/msgpool.h
@@ -11,10 +11,11 @@
struct ceph_msgpool {
const char *name;
mempool_t *pool;
+ int type; /* preallocated message type */
int front_len; /* preallocated payload size */
};
-extern int ceph_msgpool_init(struct ceph_msgpool *pool,
+extern int ceph_msgpool_init(struct ceph_msgpool *pool, int type,
int front_len, int size, bool blocking,
const char *name);
extern void ceph_msgpool_destroy(struct ceph_msgpool *pool);
--- a/net/ceph/msgpool.c
+++ b/net/ceph/msgpool.c
@@ -12,7 +12,7 @@ static void *msgpool_alloc(gfp_t gfp_mas
struct ceph_msgpool *pool = arg;
struct ceph_msg *msg;
- msg = ceph_msg_new(0, pool->front_len, gfp_mask, true);
+ msg = ceph_msg_new(pool->type, pool->front_len, gfp_mask, true);
if (!msg) {
dout("msgpool_alloc %s failed\n", pool->name);
} else {
@@ -32,10 +32,11 @@ static void msgpool_free(void *element,
ceph_msg_put(msg);
}
-int ceph_msgpool_init(struct ceph_msgpool *pool,
+int ceph_msgpool_init(struct ceph_msgpool *pool, int type,
int front_len, int size, bool blocking, const char *name)
{
dout("msgpool %s init\n", name);
+ pool->type = type;
pool->front_len = front_len;
pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool);
if (!pool->pool)
@@ -61,7 +62,7 @@ struct ceph_msg *ceph_msgpool_get(struct
WARN_ON(1);
/* try to alloc a fresh message */
- return ceph_msg_new(0, front_len, GFP_NOFS, false);
+ return ceph_msg_new(pool->type, front_len, GFP_NOFS, false);
}
msg = mempool_alloc(pool->pool, GFP_NOFS);
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -242,6 +242,7 @@ struct ceph_osd_request *ceph_osdc_alloc
}
ceph_pagelist_init(req->r_trail);
}
+
/* create request message; allow space for oid */
msg_size += MAX_OBJ_NAME_SIZE;
if (snapc)
@@ -255,7 +256,6 @@ struct ceph_osd_request *ceph_osdc_alloc
return NULL;
}
- msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP);
memset(msg->front.iov_base, 0, msg->front.iov_len);
req->r_request = msg;
@@ -1837,11 +1837,12 @@ int ceph_osdc_init(struct ceph_osd_clien
if (!osdc->req_mempool)
goto out;
- err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true,
+ err = ceph_msgpool_init(&osdc->msgpool_op, CEPH_MSG_OSD_OP,
+ OSD_OP_FRONT_LEN, 10, true,
"osd_op");
if (err < 0)
goto out_mempool;
- err = ceph_msgpool_init(&osdc->msgpool_op_reply,
+ err = ceph_msgpool_init(&osdc->msgpool_op_reply, CEPH_MSG_OSD_OPREPLY,
OSD_OPREPLY_FRONT_LEN, 10, true,
"osd_op_reply");
if (err < 0)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huang Ying <[email protected]>
commit 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e upstream.
If a PCI device and its parents are put into D3cold, unbinding the
device will trigger deadlock as follow:
- driver_unbind
- device_release_driver
- device_lock(dev) <--- previous lock here
- __device_release_driver
- pm_runtime_get_sync
...
- rpm_resume(dev)
- rpm_resume(dev->parent)
...
- pci_pm_runtime_resume
...
- pci_set_power_state
- __pci_start_power_transition
- pci_wakeup_bus(dev->parent->subordinate)
- pci_walk_bus
- device_lock(dev) <--- deadlock here
If we do not do device_lock in pci_walk_bus, we can avoid deadlock.
Device_lock in pci_walk_bus is introduced in commit:
d71374dafbba7ec3f67371d3b7e9f6310a588808, corresponding email thread
is: https://lkml.org/lkml/2006/5/26/38. The patch author Zhang Yanmin
said device_lock is added to pci_walk_bus because:
Some error handling functions call pci_walk_bus. For example, PCIe
aer. Here we lock the device, so the driver wouldn't detach from the
device, as the cb might call driver's callback function.
So I fixed the deadlock as follows:
- remove device_lock from pci_walk_bus
- add device_lock into callback if callback will call driver's callback
I checked pci_walk_bus users one by one, and found only PCIe aer needs
device lock.
Signed-off-by: Huang Ying <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Acked-by: Rafael J. Wysocki <[email protected]>
CC: Zhang Yanmin <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/pci/bus.c | 3 ---
drivers/pci/pcie/aer/aerdrv_core.c | 20 ++++++++++++++++----
2 files changed, 16 insertions(+), 7 deletions(-)
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -314,10 +314,7 @@ void pci_walk_bus(struct pci_bus *top, i
} else
next = dev->bus_list.next;
- /* Run device routines with the device locked */
- device_lock(&dev->dev);
retval = cb(dev, userdata);
- device_unlock(&dev->dev);
if (retval)
break;
}
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -244,6 +244,7 @@ static int report_error_detected(struct
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
dev->error_state = result_data->state;
if (!dev->driver ||
@@ -262,12 +263,14 @@ static int report_error_detected(struct
dev->driver ?
"no AER-aware driver" : "no driver");
}
- return 0;
+ goto out;
}
err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -278,14 +281,17 @@ static int report_mmio_enabled(struct pc
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->mmio_enabled)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
vote = err_handler->mmio_enabled(dev);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -296,14 +302,17 @@ static int report_slot_reset(struct pci_
struct aer_broadcast_data *result_data;
result_data = (struct aer_broadcast_data *) data;
+ device_lock(&dev->dev);
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->slot_reset)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
vote = err_handler->slot_reset(dev);
result_data->result = merge_result(result_data->result, vote);
+out:
+ device_unlock(&dev->dev);
return 0;
}
@@ -311,15 +320,18 @@ static int report_resume(struct pci_dev
{
struct pci_error_handlers *err_handler;
+ device_lock(&dev->dev);
dev->error_state = pci_channel_io_normal;
if (!dev->driver ||
!dev->driver->err_handler ||
!dev->driver->err_handler->resume)
- return 0;
+ goto out;
err_handler = dev->driver->err_handler;
err_handler->resume(dev);
+out:
+ device_unlock(&dev->dev);
return 0;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 6139919133377652992a5fe134e22abce3e9c25e)
We drop the lock when calling the ->alloc_msg() con op, which means
we need to (a) not clobber con->in_msg without the mutex held, and (b)
we need to verify that we are still in the OPEN state when we retake
it to avoid causing any mayhem. If the state does change, -EAGAIN
will get us back to con_work() and loop.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2735,9 +2735,16 @@ static int ceph_con_in_msg_alloc(struct
BUG_ON(con->in_msg != NULL);
if (con->ops->alloc_msg) {
+ struct ceph_msg *msg;
+
mutex_unlock(&con->mutex);
- con->in_msg = con->ops->alloc_msg(con, hdr, skip);
+ msg = con->ops->alloc_msg(con, hdr, skip);
mutex_lock(&con->mutex);
+ if (con->state != CON_STATE_OPEN) {
+ ceph_msg_put(msg);
+ return -EAGAIN;
+ }
+ con->in_msg = msg;
if (con->in_msg) {
con->in_msg->con = con->ops->get(con);
BUG_ON(con->in_msg->con == NULL);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit f3dea7edd3d449fe7a6d402c1ce56a294b985261)
(cherry picked from commit 642c0dbde32f34baa7886e988a067089992adc8f)
We need to flush the msgr workqueue during mon_client shutdown to
ensure that any work affecting our embedded ceph_connection is
finished so that we can be safely destroyed.
Previously, we were flushing the work queue after osd_client
shutdown and before mon_client shutdown to ensure that any osd
connection refs to authorizers are flushed. Remove the redundant
flush, and document in the comment that the mon_client flush is
needed to cover that case as well.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/ceph_common.c | 7 -------
net/ceph/mon_client.c | 8 ++++++++
2 files changed, 8 insertions(+), 7 deletions(-)
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -504,13 +504,6 @@ void ceph_destroy_client(struct ceph_cli
/* unmount */
ceph_osdc_stop(&client->osdc);
- /*
- * make sure osd connections close out before destroying the
- * auth module, which is needed to free those connections'
- * ceph_authorizers.
- */
- ceph_msgr_flush();
-
ceph_monc_stop(&client->monc);
ceph_debugfs_client_cleanup(client);
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -847,6 +847,14 @@ void ceph_monc_stop(struct ceph_mon_clie
mutex_unlock(&monc->mutex);
+ /*
+ * flush msgr queue before we destroy ourselves to ensure that:
+ * - any work that references our embedded con is finished.
+ * - any osd_client or other work that may reference an authorizer
+ * finishes before we shut down the auth subsystem.
+ */
+ ceph_msgr_flush();
+
ceph_auth_destroy(monc->auth);
ceph_msg_put(monc->m_auth);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
commit 1f98ab7fef48a2968f37f422c256c9fbd978c3f0 upstream.
Fixes more wifi status skb leaks, leading to hostapd/wpa_supplicant hangs.
Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/sta_info.c | 6 +++---
net/mac80211/status.c | 9 +++++++++
net/mac80211/tx.c | 9 ++++++---
4 files changed, 20 insertions(+), 6 deletions(-)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1297,6 +1297,8 @@ netdev_tx_t ieee80211_monitor_start_xmit
struct net_device *dev);
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev);
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+ struct sk_buff_head *skbs);
/* HT */
bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata);
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -738,8 +738,8 @@ int __must_check __sta_info_destroy(stru
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
- __skb_queue_purge(&sta->ps_tx_buf[ac]);
- __skb_queue_purge(&sta->tx_filtered[ac]);
+ ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
+ ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
}
#ifdef CONFIG_MAC80211_MESH
@@ -774,7 +774,7 @@ int __must_check __sta_info_destroy(stru
tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
if (!tid_tx)
continue;
- __skb_queue_purge(&tid_tx->pending);
+ ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
kfree(tid_tx);
}
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -660,3 +660,12 @@ void ieee80211_free_txskb(struct ieee802
dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(ieee80211_free_txskb);
+
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+ struct sk_buff_head *skbs)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(skbs)))
+ ieee80211_free_txskb(hw, skb);
+}
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1357,7 +1357,7 @@ static int invoke_tx_handlers(struct iee
if (tx->skb)
dev_kfree_skb(tx->skb);
else
- __skb_queue_purge(&tx->skbs);
+ ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
return -1;
} else if (unlikely(res == TX_QUEUED)) {
I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -2126,10 +2126,13 @@ netdev_tx_t ieee80211_subif_start_xmit(s
*/
void ieee80211_clear_tx_pending(struct ieee80211_local *local)
{
+ struct sk_buff *skb;
int i;
- for (i = 0; i < local->hw.queues; i++)
- skb_queue_purge(&local->pending[i]);
+ for (i = 0; i < local->hw.queues; i++) {
+ while ((skb = skb_dequeue(&local->pending[i])) != NULL)
+ ieee80211_free_txskb(&local->hw, skb);
+ }
}
/*
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 4f471e4a9c7db0256834e1b376ea50c82e345c3c)
Revoke all mon_client messages when we shut down the old connection.
This is mostly moot since we are re-using the same ceph_connection,
but it is cleaner.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/mon_client.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -118,6 +118,9 @@ static void __close_session(struct ceph_
{
dout("__close_session closing mon%d\n", monc->cur_mon);
ceph_msg_revoke(monc->m_auth);
+ ceph_msg_revoke_incoming(monc->m_auth_reply);
+ ceph_msg_revoke(monc->m_subscribe);
+ ceph_msg_revoke_incoming(monc->m_subscribe_ack);
ceph_con_close(&monc->con);
monc->cur_mon = -1;
monc->pending_auth = 0;
@@ -685,6 +688,7 @@ static void __resend_generic_request(str
for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) {
req = rb_entry(p, struct ceph_mon_generic_request, node);
ceph_msg_revoke(req->request);
+ ceph_msg_revoke_incoming(req->reply);
ceph_con_send(&monc->con, ceph_msg_get(req->request));
}
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit d329156f16306449c273002486c28de3ddddfd89)
Move the kvec reset for a connection out of prepare_write_banner and
into its only caller.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -686,7 +686,6 @@ static int prepare_connect_authorizer(st
static void prepare_write_banner(struct ceph_messenger *msgr,
struct ceph_connection *con)
{
- ceph_con_out_kvec_reset(con);
ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER);
ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr),
&msgr->my_enc_addr);
@@ -726,10 +725,9 @@ static int prepare_write_connect(struct
con->out_connect.protocol_version = cpu_to_le32(proto);
con->out_connect.flags = 0;
+ ceph_con_out_kvec_reset(con);
if (include_banner)
prepare_write_banner(msgr, con);
- else
- ceph_con_out_kvec_reset(con);
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
con->out_more = 0;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xi Wang <[email protected]>
[ Upstream commit 0c9f79be295c99ac7e4b569ca493d75fdcc19e4e ]
(1<<optname) is undefined behavior in C with a negative optname or
optname larger than 31. In those cases the result of the shift is
not necessarily zero (e.g., on x86).
This patch simplifies the code with a switch statement on optname.
It also allows the compiler to generate better code (e.g., using a
64-bit mask).
Signed-off-by: Xi Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ipv4/ip_sockglue.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -456,19 +456,28 @@ static int do_ip_setsockopt(struct sock
struct inet_sock *inet = inet_sk(sk);
int val = 0, err;
- if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
- (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
- (1<<IP_RETOPTS) | (1<<IP_TOS) |
- (1<<IP_TTL) | (1<<IP_HDRINCL) |
- (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
- (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
- (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
- (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
- optname == IP_UNICAST_IF ||
- optname == IP_MULTICAST_TTL ||
- optname == IP_MULTICAST_ALL ||
- optname == IP_MULTICAST_LOOP ||
- optname == IP_RECVORIGDSTADDR) {
+ switch (optname) {
+ case IP_PKTINFO:
+ case IP_RECVTTL:
+ case IP_RECVOPTS:
+ case IP_RECVTOS:
+ case IP_RETOPTS:
+ case IP_TOS:
+ case IP_TTL:
+ case IP_HDRINCL:
+ case IP_MTU_DISCOVER:
+ case IP_RECVERR:
+ case IP_ROUTER_ALERT:
+ case IP_FREEBIND:
+ case IP_PASSSEC:
+ case IP_TRANSPARENT:
+ case IP_MINTTL:
+ case IP_NODEFRAG:
+ case IP_UNICAST_IF:
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_ALL:
+ case IP_MULTICAST_LOOP:
+ case IP_RECVORIGDSTADDR:
if (optlen >= sizeof(int)) {
if (get_user(val, (int __user *) optval))
return -EFAULT;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cyril Brulebois <[email protected]>
commit b00e69dee4ccbb3a19989e3d4f1385bc2e3406cd upstream.
This regression was spotted between Debian squeeze and Debian wheezy
kernels (respectively based on 2.6.32 and 3.2). More info about
Wake-on-LAN issues with Realtek's 816x chipsets can be found in the
following thread: http://marc.info/?t=132079219400004
Probable regression from d4ed95d796e5126bba51466dc07e287cebc8bd19;
more chipsets are likely affected.
Tested on top of a 3.2.23 kernel.
Reported-by: Florent Fourcot <[email protected]>
Tested-by: Florent Fourcot <[email protected]>
Hinted-by: Francois Romieu <[email protected]>
Signed-off-by: Cyril Brulebois <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/ethernet/realtek/r8169.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -3488,6 +3488,8 @@ static void rtl_wol_suspend_quirk(struct
void __iomem *ioaddr = tp->mmio_addr;
switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_25:
+ case RTL_GIGA_MAC_VER_26:
case RTL_GIGA_MAC_VER_29:
case RTL_GIGA_MAC_VER_30:
case RTL_GIGA_MAC_VER_32:
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
(cherry picked from commit 26ce171915f348abd1f41da1ed139d93750d987f)
We dereference "con->in_msg" on the line after it was set to NULL.
Signed-off-by: Dan Carpenter <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -440,7 +440,7 @@ static void reset_connection(struct ceph
con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
- ceph_con_put(con->in_msg->con);
+ ceph_con_put(con);
}
con->connect_seq = 0;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Yan, Zheng" <[email protected]>
(cherry picked from commit 28c0254ede13ab575d2df5c6585ed3d4817c3e6b)
I got lots of NULL pointer dereference Oops when compiling kernel on ceph.
The bug is because the kernel page migration routine replaces some pages
in the page cache with new pages, these new pages' private can be non-zero.
Signed-off-by: Zheng Yan <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/addr.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -54,7 +54,12 @@
(CONGESTION_ON_THRESH(congestion_kb) - \
(CONGESTION_ON_THRESH(congestion_kb) >> 2))
-
+static inline struct ceph_snap_context *page_snap_context(struct page *page)
+{
+ if (PagePrivate(page))
+ return (void *)page->private;
+ return NULL;
+}
/*
* Dirty a page. Optimistically adjust accounting, on the assumption
@@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct p
{
struct inode *inode;
struct ceph_inode_info *ci;
- struct ceph_snap_context *snapc = (void *)page->private;
+ struct ceph_snap_context *snapc = page_snap_context(page);
BUG_ON(!PageLocked(page));
- BUG_ON(!page->private);
BUG_ON(!PagePrivate(page));
BUG_ON(!page->mapping);
@@ -182,7 +186,6 @@ static int ceph_releasepage(struct page
struct inode *inode = page->mapping ? page->mapping->host : NULL;
dout("%p releasepage %p idx %lu\n", inode, page, page->index);
WARN_ON(PageDirty(page));
- WARN_ON(page->private);
WARN_ON(PagePrivate(page));
return 0;
}
@@ -443,7 +446,7 @@ static int writepage_nounlock(struct pag
osdc = &fsc->client->osdc;
/* verify this is a writeable snap context */
- snapc = (void *)page->private;
+ snapc = page_snap_context(page);
if (snapc == NULL) {
dout("writepage %p page %p not dirty?\n", inode, page);
goto out;
@@ -451,7 +454,7 @@ static int writepage_nounlock(struct pag
oldest = get_oldest_context(inode, &snap_size);
if (snapc->seq > oldest->seq) {
dout("writepage %p page %p snapc %p not writeable - noop\n",
- inode, page, (void *)page->private);
+ inode, page, snapc);
/* we should only noop if called by kswapd */
WARN_ON((current->flags & PF_MEMALLOC) == 0);
ceph_put_snap_context(oldest);
@@ -591,7 +594,7 @@ static void writepages_finish(struct cep
clear_bdi_congested(&fsc->backing_dev_info,
BLK_RW_ASYNC);
- ceph_put_snap_context((void *)page->private);
+ ceph_put_snap_context(page_snap_context(page));
page->private = 0;
ClearPagePrivate(page);
dout("unlocking %d %p\n", i, page);
@@ -795,7 +798,7 @@ get_more_pages:
}
/* only if matching snap context */
- pgsnapc = (void *)page->private;
+ pgsnapc = page_snap_context(page);
if (pgsnapc->seq > snapc->seq) {
dout("page snapc %p %lld > oldest %p %lld\n",
pgsnapc, pgsnapc->seq, snapc, snapc->seq);
@@ -984,7 +987,7 @@ retry_locked:
BUG_ON(!ci->i_snap_realm);
down_read(&mdsc->snap_rwsem);
BUG_ON(!ci->i_snap_realm->cached_context);
- snapc = (void *)page->private;
+ snapc = page_snap_context(page);
if (snapc && snapc != ci->i_head_snapc) {
/*
* this page is already dirty in another (older) snap
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 456ea46865787283088b23a8a7f69244513b95f0)
In con_close_socket(), a connection's SOCK_CLOSED flag gets set and
then cleared while its shutdown method is called and its reference
gets dropped.
Previously, that flag got set only if it had not already been set,
so setting it in con_close_socket() might have prevented additional
processing being done on a socket being shut down. We no longer set
SOCK_CLOSED in the socket event routine conditionally, so setting
that bit here no longer provides whatever benefit it might have
provided before.
A race condition could still leave the SOCK_CLOSED bit set even
after we've issued the call to con_close_socket(), so we still clear
that bit after shutting the socket down. Add a comment explaining
the reason for this.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -392,10 +392,16 @@ static int con_close_socket(struct ceph_
dout("con_close_socket on %p sock %p\n", con, con->sock);
if (!con->sock)
return 0;
- set_bit(SOCK_CLOSED, &con->flags);
rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
sock_release(con->sock);
con->sock = NULL;
+
+ /*
+ * Forcibly clear the SOCK_CLOSE flag. It gets set
+ * independent of the connection mutex, and we could have
+ * received a socket close event before we had the chance to
+ * shut the socket down.
+ */
clear_bit(SOCK_CLOSED, &con->flags);
con_sock_state_closed(con);
return rc;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
(cherry picked from commit d7353dd5aaf22ed611fbcd0d4a4a12fb30659290)
If we are CLOSED, the socket is closed and we won't get these.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 ---
1 file changed, 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -296,9 +296,6 @@ static void ceph_sock_state_change(struc
dout("%s %p state = %lu sk_state = %u\n", __func__,
con, con->state, sk->sk_state);
- if (test_bit(CLOSED, &con->state))
- return;
-
switch (sk->sk_state) {
case TCP_CLOSE:
dout("%s TCP_CLOSE\n", __func__);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 6c4a19158b96ea1fb8acbe0c1d5493d9dcd2f147)
The definitions for the ceph_mds_session and ceph_osd both contain
five fields related only to "authorizers." Encapsulate those fields
into their own struct type, allowing for better isolation in some
upcoming patches.
Fix the #includes in "linux/ceph/osd_client.h" to lay out their more
complete canonical path.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 32 ++++++++++++++++----------------
fs/ceph/mds_client.h | 5 ++---
include/linux/ceph/auth.h | 8 ++++++++
include/linux/ceph/osd_client.h | 11 +++++------
net/ceph/osd_client.c | 32 ++++++++++++++++----------------
5 files changed, 47 insertions(+), 41 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -334,10 +334,10 @@ void ceph_put_mds_session(struct ceph_md
dout("mdsc put_session %p %d -> %d\n", s,
atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
if (atomic_dec_and_test(&s->s_ref)) {
- if (s->s_authorizer)
+ if (s->s_auth.authorizer)
s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer(
s->s_mdsc->fsc->client->monc.auth,
- s->s_authorizer);
+ s->s_auth.authorizer);
kfree(s);
}
}
@@ -3404,29 +3404,29 @@ static int get_authorizer(struct ceph_co
struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
int ret = 0;
- if (force_new && s->s_authorizer) {
- ac->ops->destroy_authorizer(ac, s->s_authorizer);
- s->s_authorizer = NULL;
+ if (force_new && s->s_auth.authorizer) {
+ ac->ops->destroy_authorizer(ac, s->s_auth.authorizer);
+ s->s_auth.authorizer = NULL;
}
- if (s->s_authorizer == NULL) {
+ if (s->s_auth.authorizer == NULL) {
if (ac->ops->create_authorizer) {
ret = ac->ops->create_authorizer(
ac, CEPH_ENTITY_TYPE_MDS,
- &s->s_authorizer,
- &s->s_authorizer_buf,
- &s->s_authorizer_buf_len,
- &s->s_authorizer_reply_buf,
- &s->s_authorizer_reply_buf_len);
+ &s->s_auth.authorizer,
+ &s->s_auth.authorizer_buf,
+ &s->s_auth.authorizer_buf_len,
+ &s->s_auth.authorizer_reply_buf,
+ &s->s_auth.authorizer_reply_buf_len);
if (ret)
return ret;
}
}
*proto = ac->protocol;
- *buf = s->s_authorizer_buf;
- *len = s->s_authorizer_buf_len;
- *reply_buf = s->s_authorizer_reply_buf;
- *reply_len = s->s_authorizer_reply_buf_len;
+ *buf = s->s_auth.authorizer_buf;
+ *len = s->s_auth.authorizer_buf_len;
+ *reply_buf = s->s_auth.authorizer_reply_buf;
+ *reply_len = s->s_auth.authorizer_reply_buf_len;
return 0;
}
@@ -3437,7 +3437,7 @@ static int verify_authorizer_reply(struc
struct ceph_mds_client *mdsc = s->s_mdsc;
struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
- return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
+ return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len);
}
static int invalidate_authorizer(struct ceph_connection *con)
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -11,6 +11,7 @@
#include <linux/ceph/types.h>
#include <linux/ceph/messenger.h>
#include <linux/ceph/mdsmap.h>
+#include <linux/ceph/auth.h>
/*
* Some lock dependencies:
@@ -113,9 +114,7 @@ struct ceph_mds_session {
struct ceph_connection s_con;
- struct ceph_authorizer *s_authorizer;
- void *s_authorizer_buf, *s_authorizer_reply_buf;
- size_t s_authorizer_buf_len, s_authorizer_reply_buf_len;
+ struct ceph_auth_handshake s_auth;
/* protected by s_gen_ttl_lock */
spinlock_t s_gen_ttl_lock;
--- a/include/linux/ceph/auth.h
+++ b/include/linux/ceph/auth.h
@@ -14,6 +14,14 @@
struct ceph_auth_client;
struct ceph_authorizer;
+struct ceph_auth_handshake {
+ struct ceph_authorizer *authorizer;
+ void *authorizer_buf;
+ size_t authorizer_buf_len;
+ void *authorizer_reply_buf;
+ size_t authorizer_reply_buf_len;
+};
+
struct ceph_auth_client_ops {
const char *name;
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -6,9 +6,10 @@
#include <linux/mempool.h>
#include <linux/rbtree.h>
-#include "types.h"
-#include "osdmap.h"
-#include "messenger.h"
+#include <linux/ceph/types.h>
+#include <linux/ceph/osdmap.h>
+#include <linux/ceph/messenger.h>
+#include <linux/ceph/auth.h>
/*
* Maximum object name size
@@ -40,9 +41,7 @@ struct ceph_osd {
struct list_head o_requests;
struct list_head o_linger_requests;
struct list_head o_osd_lru;
- struct ceph_authorizer *o_authorizer;
- void *o_authorizer_buf, *o_authorizer_reply_buf;
- size_t o_authorizer_buf_len, o_authorizer_reply_buf_len;
+ struct ceph_auth_handshake o_auth;
unsigned long lru_ttl;
int o_marked_for_keepalive;
struct list_head o_keepalive_item;
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -667,8 +667,8 @@ static void put_osd(struct ceph_osd *osd
if (atomic_dec_and_test(&osd->o_ref)) {
struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
- if (osd->o_authorizer)
- ac->ops->destroy_authorizer(ac, osd->o_authorizer);
+ if (osd->o_auth.authorizer)
+ ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer);
kfree(osd);
}
}
@@ -2117,27 +2117,27 @@ static int get_authorizer(struct ceph_co
struct ceph_auth_client *ac = osdc->client->monc.auth;
int ret = 0;
- if (force_new && o->o_authorizer) {
- ac->ops->destroy_authorizer(ac, o->o_authorizer);
- o->o_authorizer = NULL;
+ if (force_new && o->o_auth.authorizer) {
+ ac->ops->destroy_authorizer(ac, o->o_auth.authorizer);
+ o->o_auth.authorizer = NULL;
}
- if (o->o_authorizer == NULL) {
+ if (o->o_auth.authorizer == NULL) {
ret = ac->ops->create_authorizer(
ac, CEPH_ENTITY_TYPE_OSD,
- &o->o_authorizer,
- &o->o_authorizer_buf,
- &o->o_authorizer_buf_len,
- &o->o_authorizer_reply_buf,
- &o->o_authorizer_reply_buf_len);
+ &o->o_auth.authorizer,
+ &o->o_auth.authorizer_buf,
+ &o->o_auth.authorizer_buf_len,
+ &o->o_auth.authorizer_reply_buf,
+ &o->o_auth.authorizer_reply_buf_len);
if (ret)
return ret;
}
*proto = ac->protocol;
- *buf = o->o_authorizer_buf;
- *len = o->o_authorizer_buf_len;
- *reply_buf = o->o_authorizer_reply_buf;
- *reply_len = o->o_authorizer_reply_buf_len;
+ *buf = o->o_auth.authorizer_buf;
+ *len = o->o_auth.authorizer_buf_len;
+ *reply_buf = o->o_auth.authorizer_reply_buf;
+ *reply_len = o->o_auth.authorizer_reply_buf_len;
return 0;
}
@@ -2148,7 +2148,7 @@ static int verify_authorizer_reply(struc
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
- return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
+ return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len);
}
static int invalidate_authorizer(struct ceph_connection *con)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Durgin <[email protected]>
(cherry picked from commit 77dfe99fe3cb0b2b0545e19e2d57b7a9134ee3c0)
When a device was open at a snapshot, and snapshots were deleted or
added, data from the wrong snapshot could be read. Instead of
assuming the snap context is constant, store the actual snap id when
the device is initialized, and rely on the OSDs to signal an error
if we try reading from a snapshot that was deleted.
Signed-off-by: Josh Durgin <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/block/rbd.c | 27 +++++----------------------
1 file changed, 5 insertions(+), 22 deletions(-)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -175,8 +175,7 @@ struct rbd_device {
/* protects updating the header */
struct rw_semaphore header_rwsem;
char snap_name[RBD_MAX_SNAP_NAME_LEN];
- u32 cur_snap; /* index+1 of current snapshot within snap context
- 0 - for the head */
+ u64 snap_id; /* current snapshot id */
int read_only;
struct list_head node;
@@ -552,21 +551,6 @@ err_snapc:
return -ENOMEM;
}
-static int snap_index(struct rbd_image_header *header, int snap_num)
-{
- return header->total_snaps - snap_num;
-}
-
-static u64 cur_snap_id(struct rbd_device *rbd_dev)
-{
- struct rbd_image_header *header = &rbd_dev->header;
-
- if (!rbd_dev->cur_snap)
- return 0;
-
- return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)];
-}
-
static int snap_by_name(struct rbd_image_header *header, const char *snap_name,
u64 *seq, u64 *size)
{
@@ -605,7 +589,7 @@ static int rbd_header_set_snap(struct rb
snapc->seq = header->snap_seq;
else
snapc->seq = 0;
- dev->cur_snap = 0;
+ dev->snap_id = CEPH_NOSNAP;
dev->read_only = 0;
if (size)
*size = header->image_size;
@@ -613,8 +597,7 @@ static int rbd_header_set_snap(struct rb
ret = snap_by_name(header, dev->snap_name, &snapc->seq, size);
if (ret < 0)
goto done;
-
- dev->cur_snap = header->total_snaps - ret;
+ dev->snap_id = snapc->seq;
dev->read_only = 1;
}
@@ -1521,7 +1504,7 @@ static void rbd_rq_fn(struct request_que
coll, cur_seg);
else
rbd_req_read(rq, rbd_dev,
- cur_snap_id(rbd_dev),
+ rbd_dev->snap_id,
ofs,
op_size, bio,
coll, cur_seg);
@@ -1656,7 +1639,7 @@ static int rbd_header_add_snap(struct rb
struct ceph_mon_client *monc;
/* we should create a snapshot only if we're pointing at the head */
- if (dev->cur_snap)
+ if (dev->snap_id != CEPH_NOSNAP)
return -EINVAL;
monc = &dev->rbd_client->client->monc;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
commit d55c4c613fc4d4ad2ba0fc6fa2b57176d420f7e4 upstream.
When walking page tables we need to make sure that everything
is within bounds of the ASCE limit of the task's address space.
Otherwise we might calculate e.g. a pud pointer which is not
within a pud and dereference it.
So check against TASK_SIZE (which is the ASCE limit) before
walking page tables.
Reviewed-by: Gerald Schaefer <[email protected]>
Signed-off-by: Heiko Carstens <[email protected]>
Signed-off-by: Martin Schwidefsky <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/s390/mm/gup.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -183,7 +183,7 @@ int get_user_pages_fast(unsigned long st
addr = start;
len = (unsigned long) nr_pages << PAGE_SHIFT;
end = start + len;
- if (end < start)
+ if ((end < start) || (end > TASK_SIZE))
goto slow_irqon;
/*
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Igor Murzov <[email protected]>
commit fba4e087361605d1eed63343bb08811f097c83ee upstream.
There are systems where video module known to work fine regardless
of broken _DOD and ignoring returned value here doesn't cause
any issues later. This should fix brightness controls on some laptops.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=47861
Signed-off-by: Igor Murzov <[email protected]>
Reviewed-by: Sergey V <[email protected]>
Signed-off-by: Zhang Rui <[email protected]>
Signed-off-by: Abdallah Chatila <[email protected]>
---
drivers/acpi/video.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1345,12 +1345,15 @@ static int
acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device)
{
- int status;
+ int status = 0;
struct acpi_device *dev;
- status = acpi_video_device_enumerate(video);
- if (status)
- return status;
+ /*
+ * There are systems where video module known to work fine regardless
+ * of broken _DOD and ignoring returned value here doesn't cause
+ * any issues later.
+ */
+ acpi_video_device_enumerate(video);
list_for_each_entry(dev, &device->children, node) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit ab8cb34a4b2f60281a4b18b1f1ad23bc2313d91b)
In ceph_osdc_release_request(), a reference to the r_reply message
is dropped. But just after that, that same message is revoked if it
was in use to receive an incoming reply. Reorder these so we are
sure we hold a reference until we're actually done with the message.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
(cherry picked from commit 680584fab05efff732b5ae16ad601ba994d7b505)
---
net/ceph/osd_client.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -139,8 +139,6 @@ void ceph_osdc_release_request(struct kr
if (req->r_request)
ceph_msg_put(req->r_request);
- if (req->r_reply)
- ceph_msg_put(req->r_reply);
if (req->r_con_filling_msg) {
dout("release_request revoking pages %p from con %p\n",
req->r_pages, req->r_con_filling_msg);
@@ -148,6 +146,8 @@ void ceph_osdc_release_request(struct kr
req->r_reply);
ceph_con_put(req->r_con_filling_msg);
}
+ if (req->r_reply)
+ ceph_msg_put(req->r_reply);
if (req->r_own_pages)
ceph_release_page_vector(req->r_pages,
req->r_num_pages);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 1c20f2d26795803fc4f5155fe4fca5717a5944b6)
The function ceph_alloc_msg() is only used to allocate a message
that will be assigned to a connection's in_msg pointer. Rename the
function so this implied usage is more clear.
In addition, make that assignment inside the function (again, since
that's precisely what it's intended to be used for). This allows us
to return what is now provided via the passed-in address of a "skip"
variable. The return type is now Boolean to be explicit that there
are only two possible outcomes.
Make sure the result of an ->alloc_msg method call always sets the
value of *skip properly.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 61 +++++++++++++++++++++++++++-----------------------
net/ceph/mon_client.c | 3 ++
net/ceph/osd_client.c | 1
3 files changed, 38 insertions(+), 27 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1659,9 +1659,8 @@ static int read_partial_message_section(
return 1;
}
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
- struct ceph_msg_header *hdr,
- int *skip);
+static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
+ struct ceph_msg_header *hdr);
static int read_partial_message_pages(struct ceph_connection *con,
@@ -1744,7 +1743,6 @@ static int read_partial_message(struct c
int ret;
unsigned front_len, middle_len, data_len;
bool do_datacrc = !con->msgr->nocrc;
- int skip;
u64 seq;
u32 crc;
@@ -1797,9 +1795,7 @@ static int read_partial_message(struct c
if (!con->in_msg) {
dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
con->in_hdr.front_len, con->in_hdr.data_len);
- skip = 0;
- con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip);
- if (skip) {
+ if (ceph_con_in_msg_alloc(con, &con->in_hdr)) {
/* skip this message */
dout("alloc_msg said skip message\n");
BUG_ON(con->in_msg);
@@ -2581,46 +2577,57 @@ static int ceph_alloc_middle(struct ceph
}
/*
- * Generic message allocator, for incoming messages.
+ * Allocate a message for receiving an incoming message on a
+ * connection, and save the result in con->in_msg. Uses the
+ * connection's private alloc_msg op if available.
+ *
+ * Returns true if the message should be skipped, false otherwise.
+ * If true is returned (skip message), con->in_msg will be NULL.
+ * If false is returned, con->in_msg will contain a pointer to the
+ * newly-allocated message, or NULL in case of memory exhaustion.
*/
-static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
- struct ceph_msg_header *hdr,
- int *skip)
+static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
+ struct ceph_msg_header *hdr)
{
int type = le16_to_cpu(hdr->type);
int front_len = le32_to_cpu(hdr->front_len);
int middle_len = le32_to_cpu(hdr->middle_len);
- struct ceph_msg *msg = NULL;
int ret;
+ BUG_ON(con->in_msg != NULL);
+
if (con->ops->alloc_msg) {
+ int skip = 0;
+
mutex_unlock(&con->mutex);
- msg = con->ops->alloc_msg(con, hdr, skip);
+ con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
mutex_lock(&con->mutex);
- if (!msg || *skip)
- return NULL;
+ if (skip)
+ con->in_msg = NULL;
+
+ if (!con->in_msg)
+ return skip != 0;
}
- if (!msg) {
- *skip = 0;
- msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
- if (!msg) {
+ if (!con->in_msg) {
+ con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
+ if (!con->in_msg) {
pr_err("unable to allocate msg type %d len %d\n",
type, front_len);
- return NULL;
+ return false;
}
- msg->page_alignment = le16_to_cpu(hdr->data_off);
+ con->in_msg->page_alignment = le16_to_cpu(hdr->data_off);
}
- memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
+ memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
- if (middle_len && !msg->middle) {
- ret = ceph_alloc_middle(con, msg);
+ if (middle_len && !con->in_msg->middle) {
+ ret = ceph_alloc_middle(con, con->in_msg);
if (ret < 0) {
- ceph_msg_put(msg);
- return NULL;
+ ceph_msg_put(con->in_msg);
+ con->in_msg = NULL;
}
}
- return msg;
+ return false;
}
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -442,6 +442,7 @@ static struct ceph_msg *get_generic_repl
m = NULL;
} else {
dout("get_generic_reply %lld got %p\n", tid, req->reply);
+ *skip = 0;
m = ceph_msg_get(req->reply);
/*
* we don't need to track the connection reading into
@@ -990,6 +991,8 @@ static struct ceph_msg *mon_alloc_msg(st
case CEPH_MSG_MDS_MAP:
case CEPH_MSG_OSD_MAP:
m = ceph_msg_new(type, front_len, GFP_NOFS, false);
+ if (!m)
+ return NULL; /* ENOMEM--return skip == 0 */
break;
}
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2077,6 +2077,7 @@ static struct ceph_msg *alloc_msg(struct
int type = le16_to_cpu(hdr->type);
int front = le32_to_cpu(hdr->front_len);
+ *skip = 0;
switch (type) {
case CEPH_MSG_OSD_MAP:
case CEPH_MSG_WATCH_NOTIFY:
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 89a86be0ce20022f6ede8bccec078dbb3d63caaa)
Once we call ->connect(), we are racing against the actual
connection, and a subsequent transition from CONNECTING ->
CONNECTED. Set the state to CONNECTING before that, under the
protection of the mutex, to avoid the race.
This was introduced in 928443cd9644e7cfd46f687dbeffda2d1a357ff9,
with the original socket state code.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -321,6 +321,7 @@ static int ceph_tcp_connect(struct ceph_
dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr));
+ con_sock_state_connecting(con);
ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr),
O_NONBLOCK);
if (ret == -EINPROGRESS) {
@@ -336,8 +337,6 @@ static int ceph_tcp_connect(struct ceph_
return ret;
}
con->sock = sock;
- con_sock_state_connecting(con);
-
return 0;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryan Schumaker <[email protected]>
commit 399f11c3d872bd748e1575574de265a6304c7c43 upstream.
Currently, we will schedule session recovery and then return to the
caller of nfs4_handle_exception. This works for most cases, but causes
a hang on the following test case:
Client Server
------ ------
Open file over NFS v4.1
Write to file
Expire client
Try to lock file
The server will return NFS4ERR_BADSESSION, prompting the client to
schedule recovery. However, the client will continue placing lock
attempts and the open recovery never seems to be scheduled. The
simplest solution is to wait for session recovery to run before retrying
the lock.
Signed-off-by: Bryan Schumaker <[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/nfs/nfs4proc.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -307,8 +307,7 @@ static int nfs4_handle_exception(struct
dprintk("%s ERROR: %d Reset session\n", __func__,
errorcode);
nfs4_schedule_session_recovery(clp->cl_session);
- exception->retry = 1;
- break;
+ goto wait_on_recovery;
#endif /* defined(CONFIG_NFS_V4_1) */
case -NFS4ERR_FILE_OPEN:
if (exception->timeout > HZ) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 3a140a0d5c4b9e35373b016e41dfc85f1e526bdb)
We need to set error_msg to something useful before calling ceph_fault();
do so here for try_{read,write}(). This is more informative than
libceph: osd0 192.168.106.220:6801 (null)
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2287,14 +2287,18 @@ restart:
ret = try_read(con);
if (ret == -EAGAIN)
goto restart;
- if (ret < 0)
+ if (ret < 0) {
+ con->error_msg = "socket error on read";
goto fault;
+ }
ret = try_write(con);
if (ret == -EAGAIN)
goto restart;
- if (ret < 0)
+ if (ret < 0) {
+ con->error_msg = "socket error on write";
goto fault;
+ }
done:
mutex_unlock(&con->mutex);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 5bdca4e0768d3e0f4efa43d9a2cc8210aeb91ab9)
In ancient times, the messenger could both initiate and accept connections.
An artifact if that was data structures to store/process an incoming
ceph_msg_connect request and send an outgoing ceph_msg_connect_reply.
Sadly, the negotiation code was referencing those structures and ignoring
important information (like the peer's connect_seq) from the correct ones.
Among other things, this fixes tight reconnect loops where the server sends
RETRY_SESSION and we (the client) retries with the same connect_seq as last
time. This bug pretty easily triggered by injecting socket failures on the
MDS and running some fs workload like workunits/direct_io/test_sync_io.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 12 ++----------
net/ceph/messenger.c | 12 ++++++------
2 files changed, 8 insertions(+), 16 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -163,16 +163,8 @@ struct ceph_connection {
/* connection negotiation temps */
char in_banner[CEPH_BANNER_MAX_LEN];
- union {
- struct { /* outgoing connection */
- struct ceph_msg_connect out_connect;
- struct ceph_msg_connect_reply in_reply;
- };
- struct { /* incoming */
- struct ceph_msg_connect in_connect;
- struct ceph_msg_connect_reply out_reply;
- };
- };
+ struct ceph_msg_connect out_connect;
+ struct ceph_msg_connect_reply in_reply;
struct ceph_entity_addr actual_peer_addr;
/* message out temps */
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_c
* dropped messages.
*/
dout("process_connect got RESET peer seq %u\n",
- le32_to_cpu(con->in_connect.connect_seq));
+ le32_to_cpu(con->in_reply.connect_seq));
pr_err("%s%lld %s connection reset\n",
ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr));
@@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_c
* If we sent a smaller connect_seq than the peer has, try
* again with a larger value.
*/
- dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
+ dout("process_connect got RETRY_SESSION my seq %u, peer %u\n",
le32_to_cpu(con->out_connect.connect_seq),
- le32_to_cpu(con->in_connect.connect_seq));
- con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
+ le32_to_cpu(con->in_reply.connect_seq));
+ con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
ceph_con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
@@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_c
*/
dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
con->peer_global_seq,
- le32_to_cpu(con->in_connect.global_seq));
+ le32_to_cpu(con->in_reply.global_seq));
get_global_seq(con->msgr,
- le32_to_cpu(con->in_connect.global_seq));
+ le32_to_cpu(con->in_reply.global_seq));
ceph_con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jozsef Kadlecsik <[email protected]>
commit 64f509ce71b08d037998e93dd51180c19b2f464c upstream.
Clients should not send such packets. By accepting them, we open
up a hole by wich ephemeral ports can be discovered in an off-path
attack.
See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel,
http://arxiv.org/abs/1201.2074
Signed-off-by: Jozsef Kadlecsik <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/netfilter/nf_conntrack_proto_tcp.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP
* sCL -> sSS
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
-/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
+/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR },
/*
* sNO -> sIV Too late and no reason to do anything
* sSS -> sIV Client can't send SYN and then SYN/ACK
* sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open
- * sSR -> sIG
- * sES -> sIG Error: SYNs in window outside the SYN_SENT state
- * are errors. Receiver will reply with RST
- * and close the connection.
- * Or we are not in sync and hold a dead connection.
- * sFW -> sIG
- * sCW -> sIG
- * sLA -> sIG
- * sTW -> sIG
- * sCL -> sIG
+ * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open
+ * sES -> sIV Invalid SYN/ACK packets sent by the client
+ * sFW -> sIV
+ * sCW -> sIV
+ * sLA -> sIV
+ * sTW -> sIV
+ * sCL -> sIV
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
/*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 7b862e07b1a4d5c963d19027f10ea78085f27f9b)
We drop the con mutex when delivering a message. When we retake the
lock, we need to verify we are still in the OPEN state before
preparing to read the next tag, or else we risk stepping on a
connection that has been closed.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2003,7 +2003,6 @@ static void process_message(struct ceph_
con->ops->dispatch(con, msg);
mutex_lock(&con->mutex);
- prepare_read_tag(con);
}
@@ -2213,6 +2212,8 @@ more:
if (con->in_tag == CEPH_MSGR_TAG_READY)
goto more;
process_message(con);
+ if (con->state == CON_STATE_OPEN)
+ prepare_read_tag(con);
goto more;
}
if (con->in_tag == CEPH_MSGR_TAG_ACK) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit f671d4cd9b36691ac4ef42cde44c1b7a84e13631)
Fix the node weight lookup for tree buckets by using a correct accessor.
Reflects ceph.git commit d287ade5bcbdca82a3aef145b92924cf1e856733.
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/crush/crush.h | 5 +++++
net/ceph/crush/crush.c | 4 +---
2 files changed, 6 insertions(+), 3 deletions(-)
--- a/include/linux/crush/crush.h
+++ b/include/linux/crush/crush.h
@@ -177,4 +177,9 @@ extern void crush_destroy_bucket_straw(s
extern void crush_destroy_bucket(struct crush_bucket *b);
extern void crush_destroy(struct crush_map *map);
+static inline int crush_calc_tree_node(int i)
+{
+ return ((i+1) << 1)-1;
+}
+
#endif
--- a/net/ceph/crush/crush.c
+++ b/net/ceph/crush/crush.c
@@ -37,9 +37,7 @@ int crush_get_bucket_item_weight(const s
case CRUSH_BUCKET_LIST:
return ((struct crush_bucket_list *)b)->item_weights[p];
case CRUSH_BUCKET_TREE:
- if (p & 1)
- return ((struct crush_bucket_tree *)b)->node_weights[p];
- return 0;
+ return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)];
case CRUSH_BUCKET_STRAW:
return ((struct crush_bucket_straw *)b)->item_weights[p];
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit a4107026976f06c9a6ce8cc84a763564ee39d901)
Previously, we were opportunistically initializing the bio_iter if it
appeared to be uninitialized in the middle of the read path. The problem
is that a sequence like:
- start reading message
- initialize bio_iter
- read half a message
- messenger fault, reconnect
- restart reading message
- ** bio_iter now non-NULL, not reinitialized **
- read past end of bio, crash
Instead, initialize the bio_iter unconditionally when we allocate/claim
the message for read.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1872,6 +1872,11 @@ static int read_partial_message(struct c
else
con->in_msg_pos.page_pos = 0;
con->in_msg_pos.data_pos = 0;
+
+#ifdef CONFIG_BLOCK
+ if (m->bio)
+ init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg);
+#endif
}
/* front */
@@ -1888,10 +1893,6 @@ static int read_partial_message(struct c
if (ret <= 0)
return ret;
}
-#ifdef CONFIG_BLOCK
- if (m->bio && !m->bio_iter)
- init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg);
-#endif
/* (page) data */
while (con->in_msg_pos.data_pos < data_len) {
@@ -1902,7 +1903,7 @@ static int read_partial_message(struct c
return ret;
#ifdef CONFIG_BLOCK
} else if (m->bio) {
-
+ BUG_ON(!m->bio_iter);
ret = read_partial_message_bio(con,
&m->bio_iter, &m->bio_seg,
data_len, do_datacrc);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 7af11686933726e99af22901d622f9e161404e6b upstream.
Calls into highlevel quota code cannot happen under the write lock. These
calls take dqio_mutex which ranks above write lock. So drop write lock
before calling back into quota code.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/reiserfs/inode.c | 10 +++++++---
fs/reiserfs/stree.c | 4 ++++
fs/reiserfs/super.c | 18 ++++++++++++++----
3 files changed, 25 insertions(+), 7 deletions(-)
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1788,8 +1788,9 @@ int reiserfs_new_inode(struct reiserfs_t
BUG_ON(!th->t_trans_id);
- dquot_initialize(inode);
+ reiserfs_write_unlock(inode->i_sb);
err = dquot_alloc_inode(inode);
+ reiserfs_write_lock(inode->i_sb);
if (err)
goto out_end_trans;
if (!dir->i_nlink) {
@@ -1985,8 +1986,10 @@ int reiserfs_new_inode(struct reiserfs_t
out_end_trans:
journal_end(th, th->t_super, th->t_blocks_allocated);
+ reiserfs_write_unlock(inode->i_sb);
/* Drop can be outside and it needs more credits so it's better to have it outside */
dquot_drop(inode);
+ reiserfs_write_lock(inode->i_sb);
inode->i_flags |= S_NOQUOTA;
make_bad_inode(inode);
@@ -3109,10 +3112,9 @@ int reiserfs_setattr(struct dentry *dent
/* must be turned off for recursive notify_change calls */
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
- depth = reiserfs_write_lock_once(inode->i_sb);
if (is_quota_modification(inode, attr))
dquot_initialize(inode);
-
+ depth = reiserfs_write_lock_once(inode->i_sb);
if (attr->ia_valid & ATTR_SIZE) {
/* version 2 items will be caught by the s_maxbytes check
** done for us in vmtruncate
@@ -3176,7 +3178,9 @@ int reiserfs_setattr(struct dentry *dent
error = journal_begin(&th, inode->i_sb, jbegin_count);
if (error)
goto out;
+ reiserfs_write_unlock_once(inode->i_sb, depth);
error = dquot_transfer(inode, attr);
+ depth = reiserfs_write_lock_once(inode->i_sb);
if (error) {
journal_end(&th, inode->i_sb, jbegin_count);
goto out;
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reis
key2type(&(key->on_disk_key)));
#endif
+ reiserfs_write_unlock(inode->i_sb);
retval = dquot_alloc_space_nodirty(inode, pasted_size);
+ reiserfs_write_lock(inode->i_sb);
if (retval) {
pathrelse(search_path);
return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs
"reiserquota insert_item(): allocating %u id=%u type=%c",
quota_bytes, inode->i_uid, head2type(ih));
#endif
+ reiserfs_write_unlock(inode->i_sb);
/* We can't dirty inode here. It would be immediately written but
* appropriate stat item isn't inserted yet... */
retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+ reiserfs_write_lock(inode->i_sb);
if (retval) {
pathrelse(path);
return retval;
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -256,7 +256,9 @@ static int finish_unfinished(struct supe
retval = remove_save_link_only(s, &save_link_key, 0);
continue;
}
+ reiserfs_write_unlock(s);
dquot_initialize(inode);
+ reiserfs_write_lock(s);
if (truncate && S_ISDIR(inode->i_mode)) {
/* We got a truncate request for a dir which is impossible.
@@ -2062,13 +2064,15 @@ static int reiserfs_write_dquot(struct d
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (ret)
goto out;
+ reiserfs_write_unlock(dquot->dq_sb);
ret = dquot_commit(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -2084,13 +2088,15 @@ static int reiserfs_acquire_dquot(struct
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (ret)
goto out;
+ reiserfs_write_unlock(dquot->dq_sb);
ret = dquot_acquire(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -2104,19 +2110,21 @@ static int reiserfs_release_dquot(struct
ret =
journal_begin(&th, dquot->dq_sb,
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ reiserfs_write_unlock(dquot->dq_sb);
if (ret) {
/* Release dquot anyway to avoid endless cycle in dqput() */
dquot_release(dquot);
goto out;
}
ret = dquot_release(dquot);
+ reiserfs_write_lock(dquot->dq_sb);
err =
journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
if (!ret && err)
ret = err;
- out:
reiserfs_write_unlock(dquot->dq_sb);
+out:
return ret;
}
@@ -2141,11 +2149,13 @@ static int reiserfs_write_info(struct su
ret = journal_begin(&th, sb, 2);
if (ret)
goto out;
+ reiserfs_write_unlock(sb);
ret = dquot_commit_info(sb, type);
+ reiserfs_write_lock(sb);
err = journal_end(&th, sb, 2);
if (!ret && err)
ret = err;
- out:
+out:
reiserfs_write_unlock(sb);
return ret;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felipe Balbi <[email protected]>
commit a4f743851f74fc3e0cc40c13082e65c24139f481 upstream.
This reverts commit 957ee7270d632245b43f6feb0e70d9a5e9ea6cf6
(serial: omap: fix software flow control).
As Russell has pointed out, that commit isn't fixing
Software Flow Control at all, and it actually makes
it even more broken.
It was agreed to revert this commit and use Russell's
latest UART patches instead.
Signed-off-by: Felipe Balbi <[email protected]>
Cc: Russell King <[email protected]>
Acked-by: Tony Lindgren <[email protected]>
Cc: Andreas Bießmann <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/arm/plat-omap/include/plat/omap-serial.h | 4 ++--
drivers/tty/serial/omap-serial.c | 12 ++++++------
2 files changed, 8 insertions(+), 8 deletions(-)
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -42,10 +42,10 @@
#define OMAP_UART_WER_MOD_WKUP 0X7F
/* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX 0x8
+#define OMAP_UART_SW_TX 0x04
/* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX 0x2
+#define OMAP_UART_SW_RX 0x04
#define OMAP_UART_SYSC_RESET 0X07
#define OMAP_UART_TCR_TRIG 0X0F
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -649,19 +649,19 @@ serial_omap_configure_xonxoff
/*
* IXON Flag:
- * Flow control for OMAP.TX
- * OMAP.RX should listen for XON/XOFF
+ * Enable XON/XOFF flow control on output.
+ * Transmit XON1, XOFF1
*/
if (termios->c_iflag & IXON)
- up->efr |= OMAP_UART_SW_RX;
+ up->efr |= OMAP_UART_SW_TX;
/*
* IXOFF Flag:
- * Flow control for OMAP.RX
- * OMAP.TX should send XON/XOFF
+ * Enable XON/XOFF flow control on input.
+ * Receiver compares XON1, XOFF1.
*/
if (termios->c_iflag & IXOFF)
- up->efr |= OMAP_UART_SW_TX;
+ up->efr |= OMAP_UART_SW_RX;
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Vetter <[email protected]>
commit a9193983f4f292a82a00c72971c17ec0ee8c6c15 upstream.
The overlay on the i830M has a peculiar failure mode: It works the
first time around after boot-up, but consistenly hangs the second time
it's used.
Chris Wilson has dug out a nice errata:
"1.5.12 Clock Gating Disable for Display Register
Address Offset: 06200h–06203h
"Bit 3
Ovrunit Clock Gating Disable.
0 = Clock gating controlled by unit enabling logic
1 = Disable clock gating function
DevALM Errata ALM049: Overlay Clock Gating Must be Disabled: Overlay
& L2 Cache clock gating must be disabled in order to prevent device
hangs when turning off overlay.SW must turn off Ovrunit clock gating
(6200h) and L2 Cache clock gating (C8h)."
Now I've nowhere found that 0xc8 register and hence couldn't apply the
l2 cache workaround. But I've remembered that part of the magic that
the OVERLAY_ON/OFF commands are supposed to do is to rearrange cache
allocations so that the overlay scaler has some scratch space.
And while pondering how that could explain the hang the 2nd time we
enable the overlay, I've remembered that the old ums overlay code did
_not_ issue the OVERLAY_OFF cmd.
And indeed, disabling the OFF cmd results in the overlay working
flawlessly, so I guess we can workaround the lack of the above
workaround by simply never disabling the overlay engine once it's
enabled.
Note that we have the first part of the above w/a already implemented
in i830_init_clock_gating - leave that as-is to avoid surprises.
v2: Add a comment in the code.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=47827
Tested-by: Rhys <[email protected]>
Reviewed-by: Chris Wilson <[email protected]>
Signed-off-by: Daniel Vetter <[email protected]>
[bwh: Backported to 3.2:
- Adjust context
- s/intel_ring_emit(ring, /OUT_RING(/]
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/i915/intel_overlay.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -427,9 +427,17 @@ static int intel_overlay_off(struct inte
OUT_RING(flip_addr);
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
/* turn overlay off */
- OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
- OUT_RING(flip_addr);
- OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+ if (IS_I830(dev)) {
+ /* Workaround: Don't disable the overlay fully, since otherwise
+ * it dies on the next OVERLAY_ON cmd. */
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+ OUT_RING(MI_NOOP);
+ } else {
+ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+ OUT_RING(flip_addr);
+ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+ }
ADVANCE_LP_RING();
return intel_overlay_do_wait_request(overlay, request,
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8636ea672f0c5ab7478c42c5b6705ebd1db7eb6a)
The ceph_fault() function takes the con mutex, so we should avoid
dropping it before calling it. This fixes a potential race with
another thread calling ceph_con_close(), or _open(), or similar (we
don't reverify con->state after retaking the lock).
Add annotation so that lockdep realizes we will drop the mutex before
returning.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2336,7 +2336,6 @@ done_unlocked:
return;
fault:
- mutex_unlock(&con->mutex);
ceph_fault(con); /* error/fault path */
goto done_unlocked;
}
@@ -2347,9 +2346,8 @@ fault:
* exponential backoff
*/
static void ceph_fault(struct ceph_connection *con)
+ __releases(con->mutex)
{
- mutex_lock(&con->mutex);
-
pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
dout("fault %p state %lu to peer %s\n",
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 0d47766f14211a73eaf54cab234db134ece79f49)
There were a few direct calls to ceph_con_{get,put}() instead of the con
ops from osd_client.c. This is a bug since those ops aren't defined to
be ceph_con_get/put.
This breaks refcounting on the ceph_osd structs that contain the
ceph_connections, and could lead to all manner of strangeness.
The purpose of the ->get and ->put methods in a ceph connection are
to allow the connection to indicate it has a reference to something
external to the messaging system, *not* to indicate something
external has a reference to the connection.
[[email protected]: added that last sentence]
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
(cherry picked from commit 88ed6ea0b295f8e2383d599a04027ec596cdf97b)
---
net/ceph/osd_client.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -144,7 +144,7 @@ void ceph_osdc_release_request(struct kr
req->r_pages, req->r_con_filling_msg);
ceph_con_revoke_message(req->r_con_filling_msg,
req->r_reply);
- ceph_con_put(req->r_con_filling_msg);
+ req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
}
if (req->r_reply)
ceph_msg_put(req->r_reply);
@@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd
if (req->r_con_filling_msg == con && req->r_reply == msg) {
dout(" dropping con_filling_msg ref %p\n", con);
req->r_con_filling_msg = NULL;
- ceph_con_put(con);
+ con->ops->put(con);
}
if (!req->r_got_reply) {
@@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct
dout("get_reply revoking msg %p from old con %p\n",
req->r_reply, req->r_con_filling_msg);
ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
- ceph_con_put(req->r_con_filling_msg);
+ req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
req->r_con_filling_msg = NULL;
}
@@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct
#endif
}
*skip = 0;
- req->r_con_filling_msg = ceph_con_get(con);
+ req->r_con_filling_msg = con->ops->get(con);
dout("get_reply tid %lld %p\n", tid, m);
out:
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit fd51653f78cf40a0516e521b6de22f329c5bad8d)
Make the second argument to read_partial() be the ending input byte
position rather than the beginning offset it now represents. This
amounts to moving the addition "to + size" into the caller.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 60 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 22 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -992,10 +992,8 @@ static int prepare_read_message(struct c
static int read_partial(struct ceph_connection *con,
- int to, int size, void *object)
+ int end, int size, void *object)
{
- int end = to + size;
-
while (con->in_base_pos < end) {
int left = end - con->in_base_pos;
int have = size - left;
@@ -1013,40 +1011,52 @@ static int read_partial(struct ceph_conn
*/
static int read_partial_banner(struct ceph_connection *con)
{
- int ret, to = 0;
+ int size;
+ int end;
+ int ret;
dout("read_partial_banner %p at %d\n", con, con->in_base_pos);
/* peer's banner */
- ret = read_partial(con, to, strlen(CEPH_BANNER), con->in_banner);
+ size = strlen(CEPH_BANNER);
+ end = size;
+ ret = read_partial(con, end, size, con->in_banner);
if (ret <= 0)
goto out;
- to += strlen(CEPH_BANNER);
- ret = read_partial(con, to, sizeof(con->actual_peer_addr),
- &con->actual_peer_addr);
+
+ size = sizeof (con->actual_peer_addr);
+ end += size;
+ ret = read_partial(con, end, size, &con->actual_peer_addr);
if (ret <= 0)
goto out;
- to += sizeof(con->actual_peer_addr);
- ret = read_partial(con, to, sizeof(con->peer_addr_for_me),
- &con->peer_addr_for_me);
+
+ size = sizeof (con->peer_addr_for_me);
+ end += size;
+ ret = read_partial(con, end, size, &con->peer_addr_for_me);
if (ret <= 0)
goto out;
+
out:
return ret;
}
static int read_partial_connect(struct ceph_connection *con)
{
- int ret, to = 0;
+ int size;
+ int end;
+ int ret;
dout("read_partial_connect %p at %d\n", con, con->in_base_pos);
- ret = read_partial(con, to, sizeof(con->in_reply), &con->in_reply);
+ size = sizeof (con->in_reply);
+ end = size;
+ ret = read_partial(con, end, size, &con->in_reply);
if (ret <= 0)
goto out;
- to += sizeof(con->in_reply);
- ret = read_partial(con, to, le32_to_cpu(con->in_reply.authorizer_len),
- con->auth_reply_buf);
+
+ size = le32_to_cpu(con->in_reply.authorizer_len);
+ end += size;
+ ret = read_partial(con, end, size, con->auth_reply_buf);
if (ret <= 0)
goto out;
@@ -1495,8 +1505,10 @@ static int process_connect(struct ceph_c
*/
static int read_partial_ack(struct ceph_connection *con)
{
- return read_partial(con, 0, sizeof(con->in_temp_ack),
- &con->in_temp_ack);
+ int size = sizeof (con->in_temp_ack);
+ int end = size;
+
+ return read_partial(con, end, size, &con->in_temp_ack);
}
@@ -1629,8 +1641,9 @@ static int read_partial_message_bio(stru
static int read_partial_message(struct ceph_connection *con)
{
struct ceph_msg *m = con->in_msg;
+ int size;
+ int end;
int ret;
- int to;
unsigned front_len, middle_len, data_len;
bool do_datacrc = !con->msgr->nocrc;
int skip;
@@ -1640,7 +1653,9 @@ static int read_partial_message(struct c
dout("read_partial_message con %p msg %p\n", con, m);
/* header */
- ret = read_partial(con, 0, sizeof (con->in_hdr), &con->in_hdr);
+ size = sizeof (con->in_hdr);
+ end = size;
+ ret = read_partial(con, end, size, &con->in_hdr);
if (ret <= 0)
return ret;
@@ -1755,8 +1770,9 @@ static int read_partial_message(struct c
}
/* footer */
- to = sizeof (m->hdr);
- ret = read_partial(con, to, sizeof (m->footer), &m->footer);
+ size = sizeof (m->footer);
+ end += size;
+ ret = read_partial(con, end, size, &m->footer);
if (ret <= 0)
return ret;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 67130934fb579fdf0f2f6d745960264378b57dc8)
A monitor client has a pointer to a ceph connection structure in it.
This is the only one of the three ceph client types that do it this
way; the OSD and MDS clients embed the connection into their main
structures. There is always exactly one ceph connection for a
monitor client, so there is no need to allocate it separate from the
monitor client structure.
So switch the ceph_mon_client structure to embed its
ceph_connection structure.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/mon_client.h | 2 -
net/ceph/mon_client.c | 47 +++++++++++++++++-----------------------
2 files changed, 21 insertions(+), 28 deletions(-)
--- a/include/linux/ceph/mon_client.h
+++ b/include/linux/ceph/mon_client.h
@@ -70,7 +70,7 @@ struct ceph_mon_client {
bool hunting;
int cur_mon; /* last monitor i contacted */
unsigned long sub_sent, sub_renew_after;
- struct ceph_connection *con;
+ struct ceph_connection con;
bool have_fsid;
/* pending generic requests */
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -106,9 +106,9 @@ static void __send_prepared_auth_request
monc->pending_auth = 1;
monc->m_auth->front.iov_len = len;
monc->m_auth->hdr.front_len = cpu_to_le32(len);
- ceph_con_revoke(monc->con, monc->m_auth);
+ ceph_con_revoke(&monc->con, monc->m_auth);
ceph_msg_get(monc->m_auth); /* keep our ref */
- ceph_con_send(monc->con, monc->m_auth);
+ ceph_con_send(&monc->con, monc->m_auth);
}
/*
@@ -117,8 +117,8 @@ static void __send_prepared_auth_request
static void __close_session(struct ceph_mon_client *monc)
{
dout("__close_session closing mon%d\n", monc->cur_mon);
- ceph_con_revoke(monc->con, monc->m_auth);
- ceph_con_close(monc->con);
+ ceph_con_revoke(&monc->con, monc->m_auth);
+ ceph_con_close(&monc->con);
monc->cur_mon = -1;
monc->pending_auth = 0;
ceph_auth_reset(monc->auth);
@@ -142,9 +142,9 @@ static int __open_session(struct ceph_mo
monc->want_next_osdmap = !!monc->want_next_osdmap;
dout("open_session mon%d opening\n", monc->cur_mon);
- monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON;
- monc->con->peer_name.num = cpu_to_le64(monc->cur_mon);
- ceph_con_open(monc->con,
+ monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON;
+ monc->con.peer_name.num = cpu_to_le64(monc->cur_mon);
+ ceph_con_open(&monc->con,
&monc->monmap->mon_inst[monc->cur_mon].addr);
/* initiatiate authentication handshake */
@@ -226,8 +226,8 @@ static void __send_subscribe(struct ceph
msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
- ceph_con_revoke(monc->con, msg);
- ceph_con_send(monc->con, ceph_msg_get(msg));
+ ceph_con_revoke(&monc->con, msg);
+ ceph_con_send(&monc->con, ceph_msg_get(msg));
monc->sub_sent = jiffies | 1; /* never 0 */
}
@@ -247,7 +247,7 @@ static void handle_subscribe_ack(struct
if (monc->hunting) {
pr_info("mon%d %s session established\n",
monc->cur_mon,
- ceph_pr_addr(&monc->con->peer_addr.in_addr));
+ ceph_pr_addr(&monc->con.peer_addr.in_addr));
monc->hunting = false;
}
dout("handle_subscribe_ack after %d seconds\n", seconds);
@@ -461,7 +461,7 @@ static int do_generic_request(struct cep
req->request->hdr.tid = cpu_to_le64(req->tid);
__insert_generic_request(monc, req);
monc->num_generic_requests++;
- ceph_con_send(monc->con, ceph_msg_get(req->request));
+ ceph_con_send(&monc->con, ceph_msg_get(req->request));
mutex_unlock(&monc->mutex);
err = wait_for_completion_interruptible(&req->completion);
@@ -684,8 +684,8 @@ static void __resend_generic_request(str
for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) {
req = rb_entry(p, struct ceph_mon_generic_request, node);
- ceph_con_revoke(monc->con, req->request);
- ceph_con_send(monc->con, ceph_msg_get(req->request));
+ ceph_con_revoke(&monc->con, req->request);
+ ceph_con_send(&monc->con, ceph_msg_get(req->request));
}
}
@@ -705,7 +705,7 @@ static void delayed_work(struct work_str
__close_session(monc);
__open_session(monc); /* continue hunting */
} else {
- ceph_con_keepalive(monc->con);
+ ceph_con_keepalive(&monc->con);
__validate_auth(monc);
@@ -760,19 +760,16 @@ int ceph_monc_init(struct ceph_mon_clien
goto out;
/* connection */
- monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL);
- if (!monc->con)
- goto out_monmap;
- ceph_con_init(&monc->client->msgr, monc->con);
- monc->con->private = monc;
- monc->con->ops = &mon_con_ops;
+ ceph_con_init(&monc->client->msgr, &monc->con);
+ monc->con.private = monc;
+ monc->con.ops = &mon_con_ops;
/* authentication */
monc->auth = ceph_auth_init(cl->options->name,
cl->options->key);
if (IS_ERR(monc->auth)) {
err = PTR_ERR(monc->auth);
- goto out_con;
+ goto out_monmap;
}
monc->auth->want_keys =
CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON |
@@ -824,8 +821,6 @@ out_subscribe_ack:
ceph_msg_put(monc->m_subscribe_ack);
out_auth:
ceph_auth_destroy(monc->auth);
-out_con:
- monc->con->ops->put(monc->con);
out_monmap:
kfree(monc->monmap);
out:
@@ -841,9 +836,7 @@ void ceph_monc_stop(struct ceph_mon_clie
mutex_lock(&monc->mutex);
__close_session(monc);
- monc->con->private = NULL;
- monc->con->ops->put(monc->con);
- monc->con = NULL;
+ monc->con.private = NULL;
mutex_unlock(&monc->mutex);
@@ -1029,7 +1022,7 @@ static void mon_fault(struct ceph_connec
if (!monc->hunting)
pr_info("mon%d %s session lost, "
"hunting for new mon\n", monc->cur_mon,
- ceph_pr_addr(&monc->con->peer_addr.in_addr));
+ ceph_pr_addr(&monc->con.peer_addr.in_addr));
__close_session(monc);
if (!monc->hunting) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d59315ca8c0de00df9b363f94a2641a30961ca1c)
These are no longer used. Every ceph_connection instance is embedded in
another structure, and refcounts manipulated via the get/put ops.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 1 -
net/ceph/messenger.c | 28 +---------------------------
2 files changed, 1 insertion(+), 28 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -135,7 +135,6 @@ struct ceph_msg_pos {
*/
struct ceph_connection {
void *private;
- atomic_t nref;
const struct ceph_connection_operations *ops;
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -501,30 +501,6 @@ bool ceph_con_opened(struct ceph_connect
}
/*
- * generic get/put
- */
-struct ceph_connection *ceph_con_get(struct ceph_connection *con)
-{
- int nref = __atomic_add_unless(&con->nref, 1, 0);
-
- dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1);
-
- return nref ? con : NULL;
-}
-
-void ceph_con_put(struct ceph_connection *con)
-{
- int nref = atomic_dec_return(&con->nref);
-
- BUG_ON(nref < 0);
- if (nref == 0) {
- BUG_ON(con->sock);
- kfree(con);
- }
- dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref);
-}
-
-/*
* initialize a new connection.
*/
void ceph_con_init(struct ceph_connection *con, void *private,
@@ -535,7 +511,6 @@ void ceph_con_init(struct ceph_connectio
memset(con, 0, sizeof(*con));
con->private = private;
con->ops = ops;
- atomic_set(&con->nref, 1);
con->msgr = msgr;
con_sock_state_init(con);
@@ -1951,8 +1926,7 @@ static int try_write(struct ceph_connect
{
int ret = 1;
- dout("try_write start %p state %lu nref %d\n", con, con->state,
- atomic_read(&con->nref));
+ dout("try_write start %p state %lu\n", con, con->state);
more:
dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 84ca8fc87fcf4ab97bb8acdb59bf97bb4820cb14)
In write_partial_msg_pages(), once all the data from a page has been
sent we advance to the next one. Put the code that takes care of
this into its own function.
While modifying write_partial_msg_pages(), make its local variable
"in_trail" be Boolean, and use the local variable "msg" (which is
just the connection's current out_msg pointer) consistently.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 58 +++++++++++++++++++++++++++++----------------------
1 file changed, 34 insertions(+), 24 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -891,6 +891,33 @@ static void iter_bio_next(struct bio **b
}
#endif
+static void out_msg_pos_next(struct ceph_connection *con, struct page *page,
+ size_t len, size_t sent, bool in_trail)
+{
+ struct ceph_msg *msg = con->out_msg;
+
+ BUG_ON(!msg);
+ BUG_ON(!sent);
+
+ con->out_msg_pos.data_pos += sent;
+ con->out_msg_pos.page_pos += sent;
+ if (sent == len) {
+ con->out_msg_pos.page_pos = 0;
+ con->out_msg_pos.page++;
+ con->out_msg_pos.did_page_crc = false;
+ if (in_trail)
+ list_move_tail(&page->lru,
+ &msg->trail->head);
+ else if (msg->pagelist)
+ list_move_tail(&page->lru,
+ &msg->pagelist->head);
+#ifdef CONFIG_BLOCK
+ else if (msg->bio)
+ iter_bio_next(&msg->bio_iter, &msg->bio_seg);
+#endif
+ }
+}
+
/*
* Write as much message data payload as we can. If we finish, queue
* up the footer.
@@ -906,11 +933,11 @@ static int write_partial_msg_pages(struc
bool do_datacrc = !con->msgr->nocrc;
int ret;
int total_max_write;
- int in_trail = 0;
+ bool in_trail = false;
size_t trail_len = (msg->trail ? msg->trail->length : 0);
dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n",
- con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages,
+ con, msg, con->out_msg_pos.page, msg->nr_pages,
con->out_msg_pos.page_pos);
#ifdef CONFIG_BLOCK
@@ -934,13 +961,12 @@ static int write_partial_msg_pages(struc
/* have we reached the trail part of the data? */
if (con->out_msg_pos.data_pos >= data_len - trail_len) {
- in_trail = 1;
+ in_trail = true;
total_max_write = data_len - con->out_msg_pos.data_pos;
page = list_first_entry(&msg->trail->head,
struct page, lru);
- max_write = PAGE_SIZE;
} else if (msg->pages) {
page = msg->pages[con->out_msg_pos.page];
} else if (msg->pagelist) {
@@ -964,14 +990,14 @@ static int write_partial_msg_pages(struc
if (do_datacrc && !con->out_msg_pos.did_page_crc) {
void *base;
u32 crc;
- u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc);
+ u32 tmpcrc = le32_to_cpu(msg->footer.data_crc);
char *kaddr;
kaddr = kmap(page);
BUG_ON(kaddr == NULL);
base = kaddr + con->out_msg_pos.page_pos + bio_offset;
crc = crc32c(tmpcrc, base, len);
- con->out_msg->footer.data_crc = cpu_to_le32(crc);
+ msg->footer.data_crc = cpu_to_le32(crc);
con->out_msg_pos.did_page_crc = true;
}
ret = ceph_tcp_sendpage(con->sock, page,
@@ -984,30 +1010,14 @@ static int write_partial_msg_pages(struc
if (ret <= 0)
goto out;
- con->out_msg_pos.data_pos += ret;
- con->out_msg_pos.page_pos += ret;
- if (ret == len) {
- con->out_msg_pos.page_pos = 0;
- con->out_msg_pos.page++;
- con->out_msg_pos.did_page_crc = false;
- if (in_trail)
- list_move_tail(&page->lru,
- &msg->trail->head);
- else if (msg->pagelist)
- list_move_tail(&page->lru,
- &msg->pagelist->head);
-#ifdef CONFIG_BLOCK
- else if (msg->bio)
- iter_bio_next(&msg->bio_iter, &msg->bio_seg);
-#endif
- }
+ out_msg_pos_next(con, page, len, (size_t) ret, in_trail);
}
dout("write_partial_msg_pages %p msg %p done\n", con, msg);
/* prepare and queue up footer, too */
if (!do_datacrc)
- con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
+ msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
con_out_kvec_reset(con);
prepare_write_message_footer(con);
ret = 1;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit cd9d9f5df6098c50726200d4185e9e8da32785b3)
A recent change made changes to the rbd_client_list be protected by
a spinlock. Unfortunately in rbd_put_client(), the lock is taken
before possibly dropping the last reference to an rbd_client, and on
the last reference that eventually calls flush_workqueue() which can
sleep.
The problem was flagged by a debug spinlock warning:
BUG: spinlock wrong CPU on CPU#3, rbd/27814
The solution is to move the spinlock acquisition and release inside
rbd_client_release(), which is the spot where it's really needed for
protecting the removal of the rbd_client from the client list.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/block/rbd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -450,7 +450,9 @@ static void rbd_client_release(struct kr
struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
dout("rbd_release_client %p\n", rbdc);
+ spin_lock(&rbd_client_list_lock);
list_del(&rbdc->node);
+ spin_unlock(&rbd_client_list_lock);
ceph_destroy_client(rbdc->client);
kfree(rbdc->rbd_opts);
@@ -463,9 +465,7 @@ static void rbd_client_release(struct kr
*/
static void rbd_put_client(struct rbd_device *rbd_dev)
{
- spin_lock(&rbd_client_list_lock);
kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
- spin_unlock(&rbd_client_list_lock);
rbd_dev->rbd_client = NULL;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jozsef Kadlecsik <[email protected]>
commit 4a70bbfaef0361d27272629d1a250a937edcafe4 upstream.
We spare nothing by not validating the sequence number of dataless
ACK packets and enabling it makes harder off-path attacks.
See: "Reflection scan: an Off-Path Attack on TCP" by Jan Wrobel,
http://arxiv.org/abs/1201.2074
Signed-off-by: Jozsef Kadlecsik <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/netfilter/nf_conntrack_proto_tcp.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -627,15 +627,9 @@ static bool tcp_in_window(const struct n
ack = sack = receiver->td_end;
}
- if (seq == end
- && (!tcph->rst
- || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
+ if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)
/*
- * Packets contains no data: we assume it is valid
- * and check the ack value only.
- * However RST segments are always validated by their
- * SEQ number, except when seq == 0 (reset sent answering
- * SYN.
+ * RST sent answering SYN.
*/
seq = end = sender->td_end;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e10c758e4031a801ea4d2f8fb39bf14c2658d74b)
prepare_write_connect() prepares a connect message, then sets
WRITE_PENDING on the connection. Then *after* this, it calls
prepare_connect_authorizer(), which updates the content of the
connection buffer already queued for sending. It's also possible it
will result in prepare_write_connect() returning -EAGAIN despite the
WRITE_PENDING big getting set.
Fix this by preparing the connect authorizer first, setting the
WRITE_PENDING bit only after that is done.
Partially addresses http://tracker.newdream.net/issues/2424
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -697,6 +697,7 @@ static int prepare_write_connect(struct
{
unsigned global_seq = get_global_seq(con->msgr, 0);
int proto;
+ int ret;
switch (con->peer_name.type) {
case CEPH_ENTITY_TYPE_MON:
@@ -723,11 +724,14 @@ static int prepare_write_connect(struct
con->out_connect.flags = 0;
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
+ ret = prepare_connect_authorizer(con);
+ if (ret)
+ return ret;
con->out_more = 0;
set_bit(WRITE_PENDING, &con->state);
- return prepare_connect_authorizer(con);
+ return 0;
}
/*
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
Signed-off-by: Sage Weil <[email protected]>
(cherry picked from commit 43c7427d100769451601b8a36988ac0528ce0124)
---
net/ceph/messenger.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -528,6 +528,8 @@ void ceph_con_close(struct ceph_connecti
clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */
clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags);
clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_BACKOFF, &con->flags);
reset_connection(con);
con->peer_global_seq = 0;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 6384bb8b8e88a9c6bf2ae0d9517c2c0199177c34)
No code sets a bad_proto method in its ceph connection operations
vector, so just get rid of it.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 3 ---
net/ceph/messenger.c | 5 -----
2 files changed, 8 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -31,9 +31,6 @@ struct ceph_connection_operations {
int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
int (*invalidate_authorizer)(struct ceph_connection *con);
- /* protocol version mismatch */
- void (*bad_proto) (struct ceph_connection *con);
-
/* there was some error on the socket (disconnect, whatever) */
void (*fault) (struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1360,11 +1360,6 @@ static void fail_protocol(struct ceph_co
{
reset_connection(con);
set_bit(CLOSED, &con->state); /* in case there's queued work */
-
- mutex_unlock(&con->mutex);
- if (con->ops->bad_proto)
- con->ops->bad_proto(con);
- mutex_lock(&con->mutex);
}
static int process_connect(struct ceph_connection *con)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 38941f8031bf042dba3ced6394ba3a3b16c244ea)
When a ceph message is queued for sending it is placed on a list of
pending messages (ceph_connection->out_queue). When they are
actually sent over the wire, they are moved from that list to
another (ceph_connection->out_sent). When acknowledgement for the
message is received, it is removed from the sent messages list.
During that entire time the message is "in the possession" of a
single ceph connection. Keep track of that connection in the
message. This will be used in the next patch (and is a helpful
bit of information for debugging anyway).
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 3 +++
net/ceph/messenger.c | 27 +++++++++++++++++++++++++--
2 files changed, 28 insertions(+), 2 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -77,7 +77,10 @@ struct ceph_msg {
unsigned nr_pages; /* size of page array */
unsigned page_alignment; /* io offset in first page */
struct ceph_pagelist *pagelist; /* instead of pages */
+
+ struct ceph_connection *con;
struct list_head list_head;
+
struct kref kref;
struct bio *bio; /* instead of pages/pagelist */
struct bio *bio_iter; /* bio iterator */
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -414,6 +414,9 @@ static int con_close_socket(struct ceph_
static void ceph_msg_remove(struct ceph_msg *msg)
{
list_del_init(&msg->list_head);
+ BUG_ON(msg->con == NULL);
+ msg->con = NULL;
+
ceph_msg_put(msg);
}
static void ceph_msg_remove_list(struct list_head *head)
@@ -433,6 +436,8 @@ static void reset_connection(struct ceph
ceph_msg_remove_list(&con->out_sent);
if (con->in_msg) {
+ BUG_ON(con->in_msg->con != con);
+ con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
}
@@ -625,8 +630,10 @@ static void prepare_write_message(struct
&con->out_temp_ack);
}
+ BUG_ON(list_empty(&con->out_queue));
m = list_first_entry(&con->out_queue, struct ceph_msg, list_head);
con->out_msg = m;
+ BUG_ON(m->con != con);
/* put message on sent list */
ceph_msg_get(m);
@@ -1810,6 +1817,8 @@ static int read_partial_message(struct c
"error allocating memory for incoming message";
return -ENOMEM;
}
+
+ BUG_ON(con->in_msg->con != con);
m = con->in_msg;
m->front.iov_len = 0; /* haven't read it yet */
if (m->middle)
@@ -1905,6 +1914,8 @@ static void process_message(struct ceph_
{
struct ceph_msg *msg;
+ BUG_ON(con->in_msg->con != con);
+ con->in_msg->con = NULL;
msg = con->in_msg;
con->in_msg = NULL;
@@ -2264,6 +2275,8 @@ static void ceph_fault(struct ceph_conne
con_close_socket(con);
if (con->in_msg) {
+ BUG_ON(con->in_msg->con != con);
+ con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
}
@@ -2382,6 +2395,8 @@ void ceph_con_send(struct ceph_connectio
/* queue */
mutex_lock(&con->mutex);
+ BUG_ON(msg->con != NULL);
+ msg->con = con;
BUG_ON(!list_empty(&msg->list_head));
list_add_tail(&msg->list_head, &con->out_queue);
dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg,
@@ -2407,13 +2422,16 @@ void ceph_con_revoke(struct ceph_connect
{
mutex_lock(&con->mutex);
if (!list_empty(&msg->list_head)) {
- dout("con_revoke %p msg %p - was on queue\n", con, msg);
+ dout("%s %p msg %p - was on queue\n", __func__, con, msg);
list_del_init(&msg->list_head);
+ BUG_ON(msg->con == NULL);
+ msg->con = NULL;
+
ceph_msg_put(msg);
msg->hdr.seq = 0;
}
if (con->out_msg == msg) {
- dout("con_revoke %p msg %p - was sending\n", con, msg);
+ dout("%s %p msg %p - was sending\n", __func__, con, msg);
con->out_msg = NULL;
if (con->out_kvec_is_msg) {
con->out_skip = con->out_kvec_bytes;
@@ -2482,6 +2500,8 @@ struct ceph_msg *ceph_msg_new(int type,
if (m == NULL)
goto out;
kref_init(&m->kref);
+
+ m->con = NULL;
INIT_LIST_HEAD(&m->list_head);
m->hdr.tid = 0;
@@ -2602,6 +2622,8 @@ static bool ceph_con_in_msg_alloc(struct
mutex_unlock(&con->mutex);
con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
mutex_lock(&con->mutex);
+ if (con->in_msg)
+ con->in_msg->con = con;
if (skip)
con->in_msg = NULL;
@@ -2615,6 +2637,7 @@ static bool ceph_con_in_msg_alloc(struct
type, front_len);
return false;
}
+ con->in_msg->con = con;
con->in_msg->page_alignment = le16_to_cpu(hdr->data_off);
}
memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 327800bdc2cb9b71f4b458ca07aa9d522668dde0)
Change the names of the three socket callback functions to make it
more obvious they're specifically associated with a connection's
socket (not the ceph connection that uses it).
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -153,46 +153,46 @@ EXPORT_SYMBOL(ceph_msgr_flush);
*/
/* data available on socket, or listen socket received a connect */
-static void ceph_data_ready(struct sock *sk, int count_unused)
+static void ceph_sock_data_ready(struct sock *sk, int count_unused)
{
struct ceph_connection *con = sk->sk_user_data;
if (sk->sk_state != TCP_CLOSE_WAIT) {
- dout("ceph_data_ready on %p state = %lu, queueing work\n",
+ dout("%s on %p state = %lu, queueing work\n", __func__,
con, con->state);
queue_con(con);
}
}
/* socket has buffer space for writing */
-static void ceph_write_space(struct sock *sk)
+static void ceph_sock_write_space(struct sock *sk)
{
struct ceph_connection *con = sk->sk_user_data;
/* only queue to workqueue if there is data we want to write,
* and there is sufficient space in the socket buffer to accept
- * more data. clear SOCK_NOSPACE so that ceph_write_space()
+ * more data. clear SOCK_NOSPACE so that ceph_sock_write_space()
* doesn't get called again until try_write() fills the socket
* buffer. See net/ipv4/tcp_input.c:tcp_check_space()
* and net/core/stream.c:sk_stream_write_space().
*/
if (test_bit(WRITE_PENDING, &con->state)) {
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
- dout("ceph_write_space %p queueing write work\n", con);
+ dout("%s %p queueing write work\n", __func__, con);
clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
queue_con(con);
}
} else {
- dout("ceph_write_space %p nothing to write\n", con);
+ dout("%s %p nothing to write\n", __func__, con);
}
}
/* socket's state has changed */
-static void ceph_state_change(struct sock *sk)
+static void ceph_sock_state_change(struct sock *sk)
{
struct ceph_connection *con = sk->sk_user_data;
- dout("ceph_state_change %p state = %lu sk_state = %u\n",
+ dout("%s %p state = %lu sk_state = %u\n", __func__,
con, con->state, sk->sk_state);
if (test_bit(CLOSED, &con->state))
@@ -200,9 +200,9 @@ static void ceph_state_change(struct soc
switch (sk->sk_state) {
case TCP_CLOSE:
- dout("ceph_state_change TCP_CLOSE\n");
+ dout("%s TCP_CLOSE\n", __func__);
case TCP_CLOSE_WAIT:
- dout("ceph_state_change TCP_CLOSE_WAIT\n");
+ dout("%s TCP_CLOSE_WAIT\n", __func__);
if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) {
if (test_bit(CONNECTING, &con->state))
con->error_msg = "connection failed";
@@ -212,7 +212,7 @@ static void ceph_state_change(struct soc
}
break;
case TCP_ESTABLISHED:
- dout("ceph_state_change TCP_ESTABLISHED\n");
+ dout("%s TCP_ESTABLISHED\n", __func__);
queue_con(con);
break;
default: /* Everything else is uninteresting */
@@ -228,9 +228,9 @@ static void set_sock_callbacks(struct so
{
struct sock *sk = sock->sk;
sk->sk_user_data = con;
- sk->sk_data_ready = ceph_data_ready;
- sk->sk_write_space = ceph_write_space;
- sk->sk_state_change = ceph_state_change;
+ sk->sk_data_ready = ceph_sock_data_ready;
+ sk->sk_write_space = ceph_sock_write_space;
+ sk->sk_state_change = ceph_sock_state_change;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Stein <[email protected]>
commit 5a83b4b5a391f07141b157ac9daa51c409e71ab5 upstream.
Signed-off-by: Alexander Stein <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_cirrus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -1112,7 +1112,7 @@ static const struct hda_verb cs_coef_ini
| 0x0400 /* Disable Coefficient Auto increment */
)},
/* Beep */
- {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
+ {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
{0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
{} /* terminator */
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 6740a845b2543cc46e1902ba21bac743fbadd0dc)
ceph_con_revoke() is passed both a message and a ceph connection.
Now that any message associated with a connection holds a pointer
to that connection, there's no need to provide the connection when
revoking a message.
This has the added benefit of precluding the possibility of the
providing the wrong connection pointer. If the message's connection
pointer is null, it is not being tracked by any connection, so
revoking it is a no-op. This is supported as a convenience for
upper layers, so they can revoke a message that is not actually
"in flight."
Rename the function ceph_msg_revoke() to reflect that it is really
an operation on a message, not a connection.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 3 ++-
net/ceph/messenger.c | 7 ++++++-
net/ceph/mon_client.c | 8 ++++----
net/ceph/osd_client.c | 4 ++--
4 files changed, 14 insertions(+), 8 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -231,7 +231,8 @@ extern void ceph_con_open(struct ceph_co
extern bool ceph_con_opened(struct ceph_connection *con);
extern void ceph_con_close(struct ceph_connection *con);
extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
-extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg);
+
+extern void ceph_msg_revoke(struct ceph_msg *msg);
extern void ceph_con_revoke_message(struct ceph_connection *con,
struct ceph_msg *msg);
extern void ceph_con_keepalive(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2425,8 +2425,13 @@ EXPORT_SYMBOL(ceph_con_send);
/*
* Revoke a message that was previously queued for send
*/
-void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg)
+void ceph_msg_revoke(struct ceph_msg *msg)
{
+ struct ceph_connection *con = msg->con;
+
+ if (!con)
+ return; /* Message not in our possession */
+
mutex_lock(&con->mutex);
if (!list_empty(&msg->list_head)) {
dout("%s %p msg %p - was on queue\n", __func__, con, msg);
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -106,7 +106,7 @@ static void __send_prepared_auth_request
monc->pending_auth = 1;
monc->m_auth->front.iov_len = len;
monc->m_auth->hdr.front_len = cpu_to_le32(len);
- ceph_con_revoke(&monc->con, monc->m_auth);
+ ceph_msg_revoke(monc->m_auth);
ceph_msg_get(monc->m_auth); /* keep our ref */
ceph_con_send(&monc->con, monc->m_auth);
}
@@ -117,7 +117,7 @@ static void __send_prepared_auth_request
static void __close_session(struct ceph_mon_client *monc)
{
dout("__close_session closing mon%d\n", monc->cur_mon);
- ceph_con_revoke(&monc->con, monc->m_auth);
+ ceph_msg_revoke(monc->m_auth);
ceph_con_close(&monc->con);
monc->con.private = NULL;
monc->cur_mon = -1;
@@ -229,7 +229,7 @@ static void __send_subscribe(struct ceph
msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
- ceph_con_revoke(&monc->con, msg);
+ ceph_msg_revoke(msg);
ceph_con_send(&monc->con, ceph_msg_get(msg));
monc->sub_sent = jiffies | 1; /* never 0 */
@@ -688,7 +688,7 @@ static void __resend_generic_request(str
for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) {
req = rb_entry(p, struct ceph_mon_generic_request, node);
- ceph_con_revoke(&monc->con, req->request);
+ ceph_msg_revoke(req->request);
ceph_con_send(&monc->con, ceph_msg_get(req->request));
}
}
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -852,7 +852,7 @@ static void __unregister_request(struct
if (req->r_osd) {
/* make sure the original request isn't in flight. */
- ceph_con_revoke(&req->r_osd->o_con, req->r_request);
+ ceph_msg_revoke(req->r_request);
list_del_init(&req->r_osd_item);
if (list_empty(&req->r_osd->o_requests) &&
@@ -879,7 +879,7 @@ static void __unregister_request(struct
static void __cancel_request(struct ceph_osd_request *req)
{
if (req->r_sent && req->r_osd) {
- ceph_con_revoke(&req->r_osd->o_con, req->r_request);
+ ceph_msg_revoke(req->r_request);
req->r_sent = 0;
}
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e22004235a900213625acd6583ac913d5a30c155)
The functions ceph_con_out_kvec_reset() and ceph_con_out_kvec_add()
are entirely private functions, so drop the "ceph_" prefix in their
name to make them slightly more wieldy.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -486,14 +486,14 @@ static u32 get_global_seq(struct ceph_me
return ret;
}
-static void ceph_con_out_kvec_reset(struct ceph_connection *con)
+static void con_out_kvec_reset(struct ceph_connection *con)
{
con->out_kvec_left = 0;
con->out_kvec_bytes = 0;
con->out_kvec_cur = &con->out_kvec[0];
}
-static void ceph_con_out_kvec_add(struct ceph_connection *con,
+static void con_out_kvec_add(struct ceph_connection *con,
size_t size, void *data)
{
int index;
@@ -534,7 +534,7 @@ static void prepare_write_message(struct
struct ceph_msg *m;
u32 crc;
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
con->out_kvec_is_msg = true;
con->out_msg_done = false;
@@ -542,9 +542,9 @@ static void prepare_write_message(struct
* TCP packet that's a good thing. */
if (con->in_seq > con->in_seq_acked) {
con->in_seq_acked = con->in_seq;
- ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack);
+ con_out_kvec_add(con, sizeof (tag_ack), &tag_ack);
con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
- ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack),
+ con_out_kvec_add(con, sizeof (con->out_temp_ack),
&con->out_temp_ack);
}
@@ -576,12 +576,12 @@ static void prepare_write_message(struct
BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len);
/* tag + hdr + front + middle */
- ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg);
- ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr);
- ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base);
+ con_out_kvec_add(con, sizeof (tag_msg), &tag_msg);
+ con_out_kvec_add(con, sizeof (m->hdr), &m->hdr);
+ con_out_kvec_add(con, m->front.iov_len, m->front.iov_base);
if (m->middle)
- ceph_con_out_kvec_add(con, m->middle->vec.iov_len,
+ con_out_kvec_add(con, m->middle->vec.iov_len,
m->middle->vec.iov_base);
/* fill in crc (except data pages), footer */
@@ -630,12 +630,12 @@ static void prepare_write_ack(struct cep
con->in_seq_acked, con->in_seq);
con->in_seq_acked = con->in_seq;
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
- ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack);
+ con_out_kvec_add(con, sizeof (tag_ack), &tag_ack);
con->out_temp_ack = cpu_to_le64(con->in_seq_acked);
- ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack),
+ con_out_kvec_add(con, sizeof (con->out_temp_ack),
&con->out_temp_ack);
con->out_more = 1; /* more will follow.. eventually.. */
@@ -648,8 +648,8 @@ static void prepare_write_ack(struct cep
static void prepare_write_keepalive(struct ceph_connection *con)
{
dout("prepare_write_keepalive %p\n", con);
- ceph_con_out_kvec_reset(con);
- ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive);
+ con_out_kvec_reset(con);
+ con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive);
set_bit(WRITE_PENDING, &con->state);
}
@@ -694,8 +694,8 @@ static struct ceph_auth_handshake *get_c
*/
static void prepare_write_banner(struct ceph_connection *con)
{
- ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER);
- ceph_con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr),
+ con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER);
+ con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr),
&con->msgr->my_enc_addr);
con->out_more = 0;
@@ -742,10 +742,10 @@ static int prepare_write_connect(struct
con->out_connect.authorizer_len = auth ?
cpu_to_le32(auth->authorizer_buf_len) : 0;
- ceph_con_out_kvec_add(con, sizeof (con->out_connect),
+ con_out_kvec_add(con, sizeof (con->out_connect),
&con->out_connect);
if (auth && auth->authorizer_buf_len)
- ceph_con_out_kvec_add(con, auth->authorizer_buf_len,
+ con_out_kvec_add(con, auth->authorizer_buf_len,
auth->authorizer_buf);
con->out_more = 0;
@@ -939,7 +939,7 @@ static int write_partial_msg_pages(struc
/* prepare and queue up footer, too */
if (!do_datacrc)
con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
prepare_write_message_footer(con);
ret = 1;
out:
@@ -1402,7 +1402,7 @@ static int process_connect(struct ceph_c
return -1;
}
con->auth_retry = 1;
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_c
ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1449,7 +1449,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->out_connect.connect_seq),
le32_to_cpu(con->in_reply.connect_seq));
con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1466,7 +1466,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_reply.global_seq));
get_global_seq(con->msgr,
le32_to_cpu(con->in_reply.global_seq));
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1873,7 +1873,7 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
- ceph_con_out_kvec_reset(con);
+ con_out_kvec_reset(con);
prepare_write_banner(con);
ret = prepare_write_connect(con);
if (ret < 0)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel J Blueman <[email protected]>
commit 16337e028a6dae9fbdd718c0d42161540a668ff3 upstream.
Correctly enable the digital microphones with the right bits in the
right coeffecient registers on Cirrus CS4206/7 codecs. It also
prevents misconfiguring ADC1/2.
This fixes the digital mic on the Macbook Pro 10,1/Retina.
Based-on-patch-by: Alexander Stein <[email protected]>
Signed-off-by: Daniel J Blueman <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_cirrus.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -95,8 +95,8 @@ enum {
#define CS420X_VENDOR_NID 0x11
#define CS_DIG_OUT1_PIN_NID 0x10
#define CS_DIG_OUT2_PIN_NID 0x15
-#define CS_DMIC1_PIN_NID 0x12
-#define CS_DMIC2_PIN_NID 0x0e
+#define CS_DMIC1_PIN_NID 0x0e
+#define CS_DMIC2_PIN_NID 0x12
/* coef indices */
#define IDX_SPDIF_STAT 0x0000
@@ -1084,14 +1084,18 @@ static void init_input(struct hda_codec
cs_automic(codec);
coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+ cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+ coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
if (is_active_pin(codec, CS_DMIC2_PIN_NID))
- coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+ coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
if (is_active_pin(codec, CS_DMIC1_PIN_NID))
- coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+ coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
* No effect if SPDIF_OUT2 is
* selected in IDX_SPDIF_CTL.
*/
- cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+ cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
} else {
if (spec->mic_detect)
cs_automic(codec);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit abdaa6a849af1d63153682c11f5bbb22dacb1f6b)
Recently a bug was fixed in which the bio_iter field in a ceph
message was not being properly re-initialized when a message got
re-transmitted:
commit 43643528cce60ca184fe8197efa8e8da7c89a037
Author: Yan, Zheng <[email protected]>
rbd: Clear ceph_msg->bio_iter for retransmitted message
We are now only initializing the bio_iter field when we are about to
start to write message data (in prepare_write_message_data()),
rather than every time we are attempting to write any portion of the
message data (in write_partial_msg_pages()). This means we no
longer need to use the msg->bio_iter field as a flag.
So just don't do that any more. Trust prepare_write_message_data()
to ensure msg->bio_iter is properly initialized, every time we are
about to begin writing (or re-writing) a message's bio data.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -604,7 +604,7 @@ static void prepare_write_message_data(s
else
con->out_msg_pos.page_pos = 0;
#ifdef CONFIG_BLOCK
- if (msg->bio && !msg->bio_iter)
+ if (msg->bio)
init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
#endif
con->out_msg_pos.data_pos = 0;
@@ -672,10 +672,6 @@ static void prepare_write_message(struct
m->hdr.seq = cpu_to_le64(++con->out_seq);
m->needs_out_seq = false;
}
-#ifdef CONFIG_BLOCK
- else
- m->bio_iter = NULL;
-#endif
dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
m, con->out_seq, le16_to_cpu(m->hdr.type),
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 84fb3adf6413862cff51d8af3fce5f0b655586a2)
Reset a connection's kvec fields in the caller rather than in
prepare_write_connect(). This ends up repeating a few lines of
code but it's improving the separation between distinct operations
on the connection, which we can take advantage of later.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -725,7 +725,6 @@ static int prepare_write_connect(struct
con->out_connect.protocol_version = cpu_to_le32(proto);
con->out_connect.flags = 0;
- ceph_con_out_kvec_reset(con);
if (include_banner)
prepare_write_banner(msgr, con);
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
@@ -1389,6 +1388,7 @@ static int process_connect(struct ceph_c
return -1;
}
con->auth_retry = 1;
+ ceph_con_out_kvec_reset(con);
ret = prepare_write_connect(con->msgr, con, 0);
if (ret < 0)
return ret;
@@ -1409,6 +1409,7 @@ static int process_connect(struct ceph_c
ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
+ ceph_con_out_kvec_reset(con);
prepare_write_connect(con->msgr, con, 0);
prepare_read_connect(con);
@@ -1432,6 +1433,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->out_connect.connect_seq),
le32_to_cpu(con->in_connect.connect_seq));
con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
+ ceph_con_out_kvec_reset(con);
prepare_write_connect(con->msgr, con, 0);
prepare_read_connect(con);
break;
@@ -1446,6 +1448,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_connect.global_seq));
get_global_seq(con->msgr,
le32_to_cpu(con->in_connect.global_seq));
+ ceph_con_out_kvec_reset(con);
prepare_write_connect(con->msgr, con, 0);
prepare_read_connect(con);
break;
@@ -1851,6 +1854,7 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
+ ceph_con_out_kvec_reset(con);
prepare_write_connect(msgr, con, 1);
prepare_read_banner(con);
set_bit(CONNECTING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 3da54776e2c0385c32d143fd497a7f40a88e29dd)
Move the addition of the authorizer buffer to a connection's
out_kvec out of get_connect_authorizer() and into its caller. This
way, the caller--prepare_write_connect()--can avoid adding the
connect header to out_kvec before it has been fully initialized.
Prior to this patch, it was possible for a connect header to be
sent over the wire before the authorizer protocol or buffer length
fields were initialized. An authorizer buffer associated with that
header could also be queued to send only after the connection header
that describes it was on the wire.
Fixes http://tracker.newdream.net/issues/2424
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -656,8 +656,6 @@ static void prepare_write_keepalive(stru
static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con,
int *auth_proto)
{
- void *auth_buf;
- int auth_len;
struct ceph_auth_handshake *auth;
if (!con->ops->get_authorizer) {
@@ -680,15 +678,9 @@ static struct ceph_auth_handshake *get_c
if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
return ERR_PTR(-EAGAIN);
- auth_buf = auth->authorizer_buf;
- auth_len = auth->authorizer_buf_len;
con->auth_reply_buf = auth->authorizer_reply_buf;
con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
- con->out_connect.authorizer_len = cpu_to_le32(auth_len);
-
- if (auth_len)
- ceph_con_out_kvec_add(con, auth_len, auth_buf);
return auth;
}
@@ -737,12 +729,20 @@ static int prepare_write_connect(struct
con->out_connect.protocol_version = cpu_to_le32(proto);
con->out_connect.flags = 0;
- ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
auth_proto = CEPH_AUTH_UNKNOWN;
auth = get_connect_authorizer(con, &auth_proto);
if (IS_ERR(auth))
return PTR_ERR(auth);
+
con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
+ con->out_connect.authorizer_len = auth ?
+ cpu_to_le32(auth->authorizer_buf_len) : 0;
+
+ ceph_con_out_kvec_add(con, sizeof (con->out_connect),
+ &con->out_connect);
+ if (auth && auth->authorizer_buf_len)
+ ceph_con_out_kvec_add(con, auth->authorizer_buf_len,
+ auth->authorizer_buf);
con->out_more = 0;
set_bit(WRITE_PENDING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit bc18f4b1c850ab355e38373fbb60fd28568d84b5)
Sage liked the state diagram I put in my commit description so
I'm putting it in with the code.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 42 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -29,7 +29,47 @@
* the sender.
*/
-/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */
+/*
+ * We track the state of the socket on a given connection using
+ * values defined below. The transition to a new socket state is
+ * handled by a function which verifies we aren't coming from an
+ * unexpected state.
+ *
+ * --------
+ * | NEW* | transient initial state
+ * --------
+ * | con_sock_state_init()
+ * v
+ * ----------
+ * | CLOSED | initialized, but no socket (and no
+ * ---------- TCP connection)
+ * ^ \
+ * | \ con_sock_state_connecting()
+ * | ----------------------
+ * | \
+ * + con_sock_state_closed() \
+ * |\ \
+ * | \ \
+ * | ----------- \
+ * | | CLOSING | socket event; \
+ * | ----------- await close \
+ * | ^ |
+ * | | |
+ * | + con_sock_state_closing() |
+ * | / \ |
+ * | / --------------- |
+ * | / \ v
+ * | / --------------
+ * | / -----------------| CONNECTING | socket created, TCP
+ * | | / -------------- connect initiated
+ * | | | con_sock_state_connected()
+ * | | v
+ * -------------
+ * | CONNECTED | TCP connection established
+ * -------------
+ *
+ * State values for ceph_connection->sock_state; NEW is assumed to be 0.
+ */
#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */
#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 3ec50d1868a9e0493046400bb1fdd054c7f64ebd)
A connection state's NEGOTIATING bit gets set while in CONNECTING
state after we have successfully exchanged a ceph banner and IP
addresses with the connection's peer (the server). But that bit
is not cleared again--at least not until another connection attempt
is initiated.
Instead, clear it as soon as the connection is fully established.
Also, clear it when a socket connection gets prematurely closed
in the midst of establishing a ceph connection (in case we had
reached the point where it was set).
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1562,6 +1562,7 @@ static int process_connect(struct ceph_c
fail_protocol(con);
return -1;
}
+ clear_bit(NEGOTIATING, &con->state);
clear_bit(CONNECTING, &con->state);
con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
con->connect_seq++;
@@ -1951,7 +1952,6 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
- clear_bit(NEGOTIATING, &con->state);
set_bit(CONNECTING, &con->state);
con_out_kvec_reset(con);
@@ -2190,10 +2190,12 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
- if (test_and_clear_bit(CONNECTING, &con->state))
+ if (test_and_clear_bit(CONNECTING, &con->state)) {
+ clear_bit(NEGOTIATING, &con->state);
con->error_msg = "connection failed";
- else
+ } else {
con->error_msg = "socket closed";
+ }
goto fault;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit ab166d5aa3bc036fba7efaca6e4e43a7e9510acf)
There are two phases in the process of linking together the two ends
of a ceph connection. The first involves exchanging a banner and
IP addresses, and if that is successful a second phase exchanges
some detail about each side's connection capabilities.
When initiating a connection, the client side now queues to send
its information for both phases of this process at the same time.
This is probably a bit more efficient, but it is slightly messier
from a layering perspective in the code.
So rearrange things so that the client doesn't send the connection
information until it has received and processed the response in the
initial banner phase (in process_banner()).
Move the code (in the (con->sock == NULL) case in try_write()) that
prepares for writing the connection information, delaying doing that
until the banner exchange has completed. Move the code that begins
the transition to this second "NEGOTIATING" phase out of
process_banner() and into its caller, so preparing to write the
connection information and preparing to read the response are
adjacent to each other.
Finally, preparing to write the connection information now requires
the output kvec to be reset in all cases, so move that into the
prepare_write_connect() and delete it from all callers.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -841,6 +841,7 @@ static int prepare_write_connect(struct
con->out_connect.authorizer_len = auth ?
cpu_to_le32(auth->authorizer_buf_len) : 0;
+ con_out_kvec_reset(con);
con_out_kvec_add(con, sizeof (con->out_connect),
&con->out_connect);
if (auth && auth->authorizer_buf_len)
@@ -1430,8 +1431,6 @@ static int process_banner(struct ceph_co
ceph_pr_addr(&con->msgr->inst.addr.in_addr));
}
- set_bit(NEGOTIATING, &con->state);
- prepare_read_connect(con);
return 0;
}
@@ -1481,7 +1480,6 @@ static int process_connect(struct ceph_c
return -1;
}
con->auth_retry = 1;
- con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1502,7 +1500,6 @@ static int process_connect(struct ceph_c
ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
- con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1528,7 +1525,6 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->out_connect.connect_seq),
le32_to_cpu(con->in_reply.connect_seq));
con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
- con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1545,7 +1541,6 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_reply.global_seq));
get_global_seq(con->msgr,
le32_to_cpu(con->in_reply.global_seq));
- con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1958,9 +1953,6 @@ more:
con_out_kvec_reset(con);
prepare_write_banner(con);
- ret = prepare_write_connect(con);
- if (ret < 0)
- goto out;
prepare_read_banner(con);
BUG_ON(con->in_msg);
@@ -2073,6 +2065,16 @@ more:
ret = process_banner(con);
if (ret < 0)
goto out;
+
+ /* Banner is good, exchange connection info */
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+ goto out;
+ prepare_read_connect(con);
+ set_bit(NEGOTIATING, &con->state);
+
+ /* Send connection info before awaiting response */
+ goto out;
}
ret = read_partial_connect(con);
if (ret <= 0)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit 20f544eea03db4b498942558b882d463ce575c3e upstream.
On resume or firmware recovery, mac80211 sends a null
data packet to see if the AP is still around and hasn't
disconnected us. However, it always does this even if
it wasn't even connected before, leading to a warning
in the new channel context code. Fix this by checking
that it's associated.
Reviewed-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/mac80211/util.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1341,6 +1341,8 @@ int ieee80211_reconfig(struct ieee80211_
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type != NL80211_IFTYPE_STATION)
continue;
+ if (!sdata->u.mgd.associated)
+ continue;
ieee80211_send_nullfunc(local, sdata, 0);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8007b8d626b49c34fb146ec16dc639d8b10c862f)
If the connect() call immediately fails such that sock == NULL, we
still need con_close_socket() to reset our socket state to CLOSED.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -224,6 +224,8 @@ static void con_sock_state_init(struct c
old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED);
if (WARN_ON(old_state != CON_SOCK_STATE_NEW))
printk("%s: unexpected old state %d\n", __func__, old_state);
+ dout("%s con %p sock %d -> %d\n", __func__, con, old_state,
+ CON_SOCK_STATE_CLOSED);
}
static void con_sock_state_connecting(struct ceph_connection *con)
@@ -233,6 +235,8 @@ static void con_sock_state_connecting(st
old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING);
if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED))
printk("%s: unexpected old state %d\n", __func__, old_state);
+ dout("%s con %p sock %d -> %d\n", __func__, con, old_state,
+ CON_SOCK_STATE_CONNECTING);
}
static void con_sock_state_connected(struct ceph_connection *con)
@@ -242,6 +246,8 @@ static void con_sock_state_connected(str
old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED);
if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING))
printk("%s: unexpected old state %d\n", __func__, old_state);
+ dout("%s con %p sock %d -> %d\n", __func__, con, old_state,
+ CON_SOCK_STATE_CONNECTED);
}
static void con_sock_state_closing(struct ceph_connection *con)
@@ -253,6 +259,8 @@ static void con_sock_state_closing(struc
old_state != CON_SOCK_STATE_CONNECTED &&
old_state != CON_SOCK_STATE_CLOSING))
printk("%s: unexpected old state %d\n", __func__, old_state);
+ dout("%s con %p sock %d -> %d\n", __func__, con, old_state,
+ CON_SOCK_STATE_CLOSING);
}
static void con_sock_state_closed(struct ceph_connection *con)
@@ -262,8 +270,11 @@ static void con_sock_state_closed(struct
old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED);
if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED &&
old_state != CON_SOCK_STATE_CLOSING &&
- old_state != CON_SOCK_STATE_CONNECTING))
+ old_state != CON_SOCK_STATE_CONNECTING &&
+ old_state != CON_SOCK_STATE_CLOSED))
printk("%s: unexpected old state %d\n", __func__, old_state);
+ dout("%s con %p sock %d -> %d\n", __func__, con, old_state,
+ CON_SOCK_STATE_CLOSED);
}
/*
@@ -448,14 +459,14 @@ static int ceph_tcp_sendpage(struct sock
*/
static int con_close_socket(struct ceph_connection *con)
{
- int rc;
+ int rc = 0;
dout("con_close_socket on %p sock %p\n", con, con->sock);
- if (!con->sock)
- return 0;
- rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
- sock_release(con->sock);
- con->sock = NULL;
+ if (con->sock) {
+ rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
+ sock_release(con->sock);
+ con->sock = NULL;
+ }
/*
* Forcibly clear the SOCK_CLOSED flag. It gets set
@@ -464,6 +475,7 @@ static int con_close_socket(struct ceph_
* shut the socket down.
*/
clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags);
+
con_sock_state_closed(con);
return rc;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Williams <[email protected]>
commit fcb21645f1bd86d2be29baf48aa1b298de52ccc7 upstream.
The Dell 5800 appears to be a simple rebrand of the Novatel E362.
Signed-off-by: Dan Williams <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/option.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -157,6 +157,7 @@ static void option_instat_callback(struc
#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
+#define NOVATELWIRELESS_PRODUCT_E362 0x9010
#define NOVATELWIRELESS_PRODUCT_G1 0xA001
#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
@@ -192,6 +193,9 @@ static void option_instat_callback(struc
#define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181
#define DELL_PRODUCT_5730_MINICARD_VZW 0x8182
+#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */
+
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
@@ -705,6 +709,7 @@ static const struct usb_device_id option
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -727,6 +732,8 @@ static const struct usb_device_id option
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit b9196395c905edec512dfd6690428084228c16ec upstream.
Fixes:
https://bugzilla.kernel.org/show_bug.cgi?id=50431
Reported-by: David Binderman <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
Reviewed-by: Michel Dänzer <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/radeon/atombios_encoders.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -1421,7 +1421,7 @@ radeon_atom_encoder_dpms_dig(struct drm_
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
/* some early dce3.2 boards have a bug in their transmitter control table */
- if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+ if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
}
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 735a72ef952d42a256f79ae3e6dc1c17a45c041b)
Do not re-initialize the con on every connection attempt. When we
ceph_con_close, there may still be work queued on the socket (e.g., to
close it), and re-initializing will clobber the work_struct state.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/mon_client.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -119,7 +119,6 @@ static void __close_session(struct ceph_
dout("__close_session closing mon%d\n", monc->cur_mon);
ceph_msg_revoke(monc->m_auth);
ceph_con_close(&monc->con);
- monc->con.private = NULL;
monc->cur_mon = -1;
monc->pending_auth = 0;
ceph_auth_reset(monc->auth);
@@ -142,9 +141,6 @@ static int __open_session(struct ceph_mo
monc->sub_renew_after = jiffies; /* i.e., expired */
monc->want_next_osdmap = !!monc->want_next_osdmap;
- ceph_con_init(&monc->con, monc, &mon_con_ops,
- &monc->client->msgr);
-
dout("open_session mon%d opening\n", monc->cur_mon);
ceph_con_open(&monc->con,
CEPH_ENTITY_TYPE_MON, monc->cur_mon,
@@ -798,6 +794,9 @@ int ceph_monc_init(struct ceph_mon_clien
if (!monc->m_auth)
goto out_auth_reply;
+ ceph_con_init(&monc->con, monc, &mon_con_ops,
+ &monc->client->msgr);
+
monc->cur_mon = -1;
monc->hunting = true;
monc->sub_renew_after = jiffies;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 8f43fb53894079bf0caab6e348ceaffe7adc651a)
Rather than passing a bunch of arguments to be filled in with the
content of the ceph_auth_handshake buffer now returned by the
get_authorizer method, just use the returned information in the
caller, and drop the unnecessary arguments.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 9 +--------
include/linux/ceph/messenger.h | 4 +---
net/ceph/messenger.c | 13 +++++++------
net/ceph/osd_client.c | 9 +--------
4 files changed, 10 insertions(+), 25 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3401,9 +3401,7 @@ out:
* managed separately. Caller must *not* attempt to free it.
*/
static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len,
- int force_new)
+ int *proto, int force_new)
{
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
@@ -3421,12 +3419,7 @@ static struct ceph_auth_handshake *get_a
if (ret)
return ERR_PTR(ret);
}
-
*proto = ac->protocol;
- *buf = auth->authorizer_buf;
- *len = auth->authorizer_buf_len;
- *reply_buf = auth->authorizer_reply_buf;
- *reply_len = auth->authorizer_reply_buf_len;
return auth;
}
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -27,9 +27,7 @@ struct ceph_connection_operations {
/* authorize an outgoing connection */
struct ceph_auth_handshake *(*get_authorizer) (
struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len,
- int force_new);
+ int *proto, int force_new);
int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
int (*invalidate_authorizer)(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -671,20 +671,21 @@ static int prepare_connect_authorizer(st
mutex_unlock(&con->mutex);
- auth_buf = NULL;
- auth_len = 0;
auth_protocol = CEPH_AUTH_UNKNOWN;
- auth = con->ops->get_authorizer(con, &auth_buf, &auth_len,
- &auth_protocol, &con->auth_reply_buf,
- &con->auth_reply_buf_len, con->auth_retry);
+ auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry);
+
mutex_lock(&con->mutex);
if (IS_ERR(auth))
return PTR_ERR(auth);
-
if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
return -EAGAIN;
+ auth_buf = auth->authorizer_buf;
+ auth_len = auth->authorizer_buf_len;
+ con->auth_reply_buf = auth->authorizer_reply_buf;
+ con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
+
con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
con->out_connect.authorizer_len = cpu_to_le32(auth_len);
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2113,9 +2113,7 @@ static void put_osd_con(struct ceph_conn
* managed separately. Caller must *not* attempt to free it.
*/
static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len,
- int force_new)
+ int *proto, int force_new)
{
struct ceph_osd *o = con->private;
struct ceph_osd_client *osdc = o->o_osdc;
@@ -2133,12 +2131,7 @@ static struct ceph_auth_handshake *get_a
if (ret)
return ERR_PTR(ret);
}
-
*proto = ac->protocol;
- *buf = auth->authorizer_buf;
- *len = auth->authorizer_buf_len;
- *reply_buf = auth->authorizer_reply_buf;
- *reply_len = auth->authorizer_reply_buf_len;
return auth;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit bb9e6bba5d8b85b631390f8dbe8a24ae1ff5b48a)
A connection that is closed will no longer be connecting. So
clear the CONNECTING state bit in ceph_con_close(). Similarly,
if the socket has been closed we no longer are in connecting
state (a new connect sequence will need to be initiated).
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -462,6 +462,7 @@ void ceph_con_close(struct ceph_connecti
dout("con_close %p peer %s\n", con,
ceph_pr_addr(&con->peer_addr.in_addr));
clear_bit(NEGOTIATING, &con->state);
+ clear_bit(CONNECTING, &con->state);
clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */
set_bit(CLOSED, &con->state);
@@ -2189,7 +2190,7 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
- if (test_bit(CONNECTING, &con->state))
+ if (test_and_clear_bit(CONNECTING, &con->state))
con->error_msg = "connection failed";
else
con->error_msg = "socket closed";
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit c90f95ed46393e29d843686e21947d1c6fcb1164)
This small adjustment reflects a change that was made in ceph.git commit
af6a9f30696c900a2a8bd7ae24e8ed15fb4964bb, about 6 months ago. An N-1
search is not exhaustive. Fixed ceph.git bug #1594.
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/crush/mapper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ceph/crush/mapper.c
+++ b/net/ceph/crush/mapper.c
@@ -415,7 +415,7 @@ reject:
if (collide && flocal < 3)
/* retry locally a few times */
retry_bucket = 1;
- else if (flocal < in->size + orig_tries)
+ else if (flocal <= in->size + orig_tries)
/* exhaustive bucket search */
retry_bucket = 1;
else if (ftotal < 20)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 85effe183dd45854d1ad1a370b88cddb403c4c91)
We exponentially back off when we encounter connection errors. If several
errors accumulate, we will eventually wait ages before even trying to
reconnect.
Fix this by resetting the backoff counter after a successful negotiation/
connection with the remote node. Fixes ceph issue #2802.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1629,6 +1629,8 @@ static int process_connect(struct ceph_c
if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
set_bit(LOSSYTX, &con->flags);
+ con->delay = 0; /* reset backoff memory */
+
prepare_read_tag(con);
break;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e825a66df97776d30a48a187e3a986736af43945)
In all cases, the value passed as the msgr argument to
prepare_write_connect() is just con->msgr. Just get the msgr
value from the ceph connection and drop the unneeded argument.
The only msgr passed to prepare_write_banner() is also therefore
just the one from con->msgr, so change that function to drop the
msgr argument as well.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -683,19 +683,17 @@ static int prepare_connect_authorizer(st
/*
* We connected to a peer and are saying hello.
*/
-static void prepare_write_banner(struct ceph_messenger *msgr,
- struct ceph_connection *con)
+static void prepare_write_banner(struct ceph_connection *con)
{
ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER);
- ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr),
- &msgr->my_enc_addr);
+ ceph_con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr),
+ &con->msgr->my_enc_addr);
con->out_more = 0;
set_bit(WRITE_PENDING, &con->state);
}
-static int prepare_write_connect(struct ceph_messenger *msgr,
- struct ceph_connection *con)
+static int prepare_write_connect(struct ceph_connection *con)
{
unsigned global_seq = get_global_seq(con->msgr, 0);
int proto;
@@ -717,7 +715,7 @@ static int prepare_write_connect(struct
dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
con->connect_seq, global_seq, proto);
- con->out_connect.features = cpu_to_le64(msgr->supported_features);
+ con->out_connect.features = cpu_to_le64(con->msgr->supported_features);
con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -1386,7 +1384,7 @@ static int process_connect(struct ceph_c
}
con->auth_retry = 1;
ceph_con_out_kvec_reset(con);
- ret = prepare_write_connect(con->msgr, con);
+ ret = prepare_write_connect(con);
if (ret < 0)
return ret;
prepare_read_connect(con);
@@ -1407,7 +1405,7 @@ static int process_connect(struct ceph_c
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con);
+ prepare_write_connect(con);
prepare_read_connect(con);
/* Tell ceph about it. */
@@ -1431,7 +1429,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_connect.connect_seq));
con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con);
+ prepare_write_connect(con);
prepare_read_connect(con);
break;
@@ -1446,7 +1444,7 @@ static int process_connect(struct ceph_c
get_global_seq(con->msgr,
le32_to_cpu(con->in_connect.global_seq));
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con);
+ prepare_write_connect(con);
prepare_read_connect(con);
break;
@@ -1840,7 +1838,6 @@ static void process_message(struct ceph_
*/
static int try_write(struct ceph_connection *con)
{
- struct ceph_messenger *msgr = con->msgr;
int ret = 1;
dout("try_write start %p state %lu nref %d\n", con, con->state,
@@ -1852,8 +1849,8 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
ceph_con_out_kvec_reset(con);
- prepare_write_banner(msgr, con);
- prepare_write_connect(msgr, con);
+ prepare_write_banner(con);
+ prepare_write_connect(con);
prepare_read_banner(con);
set_bit(CONNECTING, &con->state);
clear_bit(NEGOTIATING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 41b90c00858129f52d08e6a05c9cfdb0f2bd074d)
prepare_write_connect() has an argument indicating whether a banner
should be sent out before sending out a connection message. It's
only ever set in one of its callers, so move the code that arranges
to send the banner into that caller and drop the "include_banner"
argument from prepare_write_connect().
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -695,8 +695,7 @@ static void prepare_write_banner(struct
}
static int prepare_write_connect(struct ceph_messenger *msgr,
- struct ceph_connection *con,
- int include_banner)
+ struct ceph_connection *con)
{
unsigned global_seq = get_global_seq(con->msgr, 0);
int proto;
@@ -725,8 +724,6 @@ static int prepare_write_connect(struct
con->out_connect.protocol_version = cpu_to_le32(proto);
con->out_connect.flags = 0;
- if (include_banner)
- prepare_write_banner(msgr, con);
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
con->out_more = 0;
@@ -1389,7 +1386,7 @@ static int process_connect(struct ceph_c
}
con->auth_retry = 1;
ceph_con_out_kvec_reset(con);
- ret = prepare_write_connect(con->msgr, con, 0);
+ ret = prepare_write_connect(con->msgr, con);
if (ret < 0)
return ret;
prepare_read_connect(con);
@@ -1410,7 +1407,7 @@ static int process_connect(struct ceph_c
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con, 0);
+ prepare_write_connect(con->msgr, con);
prepare_read_connect(con);
/* Tell ceph about it. */
@@ -1434,7 +1431,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_connect.connect_seq));
con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con, 0);
+ prepare_write_connect(con->msgr, con);
prepare_read_connect(con);
break;
@@ -1449,7 +1446,7 @@ static int process_connect(struct ceph_c
get_global_seq(con->msgr,
le32_to_cpu(con->in_connect.global_seq));
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con->msgr, con, 0);
+ prepare_write_connect(con->msgr, con);
prepare_read_connect(con);
break;
@@ -1855,7 +1852,8 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
ceph_con_out_kvec_reset(con);
- prepare_write_connect(msgr, con, 1);
+ prepare_write_banner(msgr, con);
+ prepare_write_connect(msgr, con);
prepare_read_banner(con);
set_bit(CONNECTING, &con->state);
clear_bit(NEGOTIATING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirko Lindner <[email protected]>
commit d663d181b9e92d80c2455e460e932d34e7a2a7ae upstream.
Re-enable interrupts if it is not our interrupt
Signed-off-by: Mirko Lindner <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Cc: Jonathan Nieder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/ethernet/marvell/sky2.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -3079,8 +3079,10 @@ static irqreturn_t sky2_intr(int irq, vo
/* Reading this mask interrupts as side effect */
status = sky2_read32(hw, B0_Y2_SP_ISRC2);
- if (status == 0 || status == ~0)
+ if (status == 0 || status == ~0) {
+ sky2_write32(hw, B0_Y2_SP_ICR, 2);
return IRQ_NONE;
+ }
prefetch(&hw->st_le[hw->st_idx]);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 6285bc231277419255f3498d3eb5ddc9f8e7fe79)
A pgoff_t is defined (by default) to have type (unsigned long). On
architectures such as i686 that's a 32-bit type. The ceph address
space code was attempting to produce 64 bit offsets by shifting a
page's index by PAGE_CACHE_SHIFT, but the result was not what was
desired because the shift occurred before the result got promoted
to 64 bits.
Fix this by converting all uses of page->index used in this way to
use the page_offset() macro, which ensures the 64-bit result has the
intended value.
This fixes http://tracker.newdream.net/issues/3112
Reported-by: Mohamed Pakkeer <[email protected]>
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/addr.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -205,7 +205,7 @@ static int readpage_nounlock(struct file
dout("readpage inode %p file %p page %p index %lu\n",
inode, filp, page, page->index);
err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout,
- page->index << PAGE_CACHE_SHIFT, &len,
+ (u64) page_offset(page), &len,
ci->i_truncate_seq, ci->i_truncate_size,
&page, 1, 0);
if (err == -ENOENT)
@@ -286,7 +286,7 @@ static int start_read(struct inode *inod
int nr_pages = 0;
int ret;
- off = page->index << PAGE_CACHE_SHIFT;
+ off = (u64) page_offset(page);
/* count pages */
next_index = page->index;
@@ -426,7 +426,7 @@ static int writepage_nounlock(struct pag
struct ceph_inode_info *ci;
struct ceph_fs_client *fsc;
struct ceph_osd_client *osdc;
- loff_t page_off = page->index << PAGE_CACHE_SHIFT;
+ loff_t page_off = page_offset(page);
int len = PAGE_CACHE_SIZE;
loff_t i_size;
int err = 0;
@@ -817,8 +817,7 @@ get_more_pages:
/* ok */
if (locked_pages == 0) {
/* prepare async write request */
- offset = (unsigned long long)page->index
- << PAGE_CACHE_SHIFT;
+ offset = (u64) page_offset(page);
len = wsize;
req = ceph_osdc_new_request(&fsc->client->osdc,
&ci->i_layout,
@@ -1180,7 +1179,7 @@ static int ceph_page_mkwrite(struct vm_a
struct inode *inode = vma->vm_file->f_dentry->d_inode;
struct page *page = vmf->page;
struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
- loff_t off = page->index << PAGE_CACHE_SHIFT;
+ loff_t off = page_offset(page);
loff_t size, len;
int ret;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
commit 43c771a1963ab461a2f194e3c97fded1d5fe262f upstream.
When in world roaming mode, allow 40 MHz to be used
on channels 12 and 13 so that an AP that is, e.g.,
using HT40+ on channel 9 (in the UK) can be used.
Reported-by: Eddie Chapman <[email protected]>
Tested-by: Eddie Chapman <[email protected]>
Acked-by: Luis R. Rodriguez <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/wireless/reg.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -134,9 +134,8 @@ static const struct ieee80211_regdomain
.reg_rules = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
- /* IEEE 802.11b/g, channels 12..13. No HT40
- * channel fits here. */
- REG_RULE(2467-10, 2472+10, 20, 6, 20,
+ /* IEEE 802.11b/g, channels 12..13. */
+ REG_RULE(2467-10, 2472+10, 40, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
/* IEEE 802.11 channel 14 - Only JP enables
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit a3530df33eb91d787d08c7383a0a9982690e42d0)
Have the get_authorizer auth_client method return a ceph_auth
pointer rather than an integer, pointer-encoding any returned
error value. This is to pave the way for making use of the
returned value in an upcoming patch.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 20 +++++++++++++-------
include/linux/ceph/messenger.h | 8 +++++---
net/ceph/messenger.c | 8 ++++----
net/ceph/osd_client.c | 19 ++++++++++++-------
4 files changed, 34 insertions(+), 21 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3395,15 +3395,20 @@ out:
/*
* authentication
*/
-static int get_authorizer(struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len, int force_new)
+
+/*
+ * Note: returned pointer is the address of a structure that's
+ * managed separately. Caller must *not* attempt to free it.
+ */
+static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
+ void **buf, int *len, int *proto,
+ void **reply_buf, int *reply_len,
+ int force_new)
{
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
struct ceph_auth_handshake *auth = &s->s_auth;
- int ret = 0;
if (force_new && auth->authorizer) {
if (ac->ops && ac->ops->destroy_authorizer)
@@ -3411,9 +3416,10 @@ static int get_authorizer(struct ceph_co
auth->authorizer = NULL;
}
if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
- ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth);
+ int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS,
+ auth);
if (ret)
- return ret;
+ return ERR_PTR(ret);
}
*proto = ac->protocol;
@@ -3422,7 +3428,7 @@ static int get_authorizer(struct ceph_co
*reply_buf = auth->authorizer_reply_buf;
*reply_len = auth->authorizer_reply_buf_len;
- return 0;
+ return auth;
}
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -25,9 +25,11 @@ struct ceph_connection_operations {
void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
/* authorize an outgoing connection */
- int (*get_authorizer) (struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len, int force_new);
+ struct ceph_auth_handshake *(*get_authorizer) (
+ struct ceph_connection *con,
+ void **buf, int *len, int *proto,
+ void **reply_buf, int *reply_len,
+ int force_new);
int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
int (*invalidate_authorizer)(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -658,7 +658,7 @@ static int prepare_connect_authorizer(st
void *auth_buf;
int auth_len;
int auth_protocol;
- int ret;
+ struct ceph_auth_handshake *auth;
if (!con->ops->get_authorizer) {
con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
@@ -674,13 +674,13 @@ static int prepare_connect_authorizer(st
auth_buf = NULL;
auth_len = 0;
auth_protocol = CEPH_AUTH_UNKNOWN;
- ret = con->ops->get_authorizer(con, &auth_buf, &auth_len,
+ auth = con->ops->get_authorizer(con, &auth_buf, &auth_len,
&auth_protocol, &con->auth_reply_buf,
&con->auth_reply_buf_len, con->auth_retry);
mutex_lock(&con->mutex);
- if (ret)
- return ret;
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
return -EAGAIN;
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2108,15 +2108,19 @@ static void put_osd_con(struct ceph_conn
/*
* authentication
*/
-static int get_authorizer(struct ceph_connection *con,
- void **buf, int *len, int *proto,
- void **reply_buf, int *reply_len, int force_new)
+/*
+ * Note: returned pointer is the address of a structure that's
+ * managed separately. Caller must *not* attempt to free it.
+ */
+static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
+ void **buf, int *len, int *proto,
+ void **reply_buf, int *reply_len,
+ int force_new)
{
struct ceph_osd *o = con->private;
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
struct ceph_auth_handshake *auth = &o->o_auth;
- int ret = 0;
if (force_new && auth->authorizer) {
if (ac->ops && ac->ops->destroy_authorizer)
@@ -2124,9 +2128,10 @@ static int get_authorizer(struct ceph_co
auth->authorizer = NULL;
}
if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
- ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth);
+ int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD,
+ auth);
if (ret)
- return ret;
+ return ERR_PTR(ret);
}
*proto = ac->protocol;
@@ -2135,7 +2140,7 @@ static int get_authorizer(struct ceph_co
*reply_buf = auth->authorizer_reply_buf;
*reply_len = auth->authorizer_reply_buf_len;
- return 0;
+ return auth;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xi Wang <[email protected]>
(cherry picked from commit e91a9b639a691e0982088b5954eaafb5a25c8f1c)
On 32-bit systems, a large `n' would overflow `n * sizeof(u32)' and bypass
the check ceph_decode_need(p, end, n * sizeof(u32), bad). It would also
overflow the subsequent kmalloc() size, leading to out-of-bounds write.
Signed-off-by: Xi Wang <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osdmap.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -674,6 +674,9 @@ struct ceph_osdmap *osdmap_decode(void *
ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
ceph_decode_copy(p, &pgid, sizeof(pgid));
n = ceph_decode_32(p);
+ err = -EINVAL;
+ if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
+ goto bad;
ceph_decode_need(p, end, n * sizeof(u32), bad);
err = -ENOMEM;
pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 6194ea895e447fdf4adfd23f67873a32bf4f15ae)
The linger op registration (i.e., watch) modifies the object state. As
such, the OSD will reply with success if it has already applied without
doing the associated side-effects (setting up the watch session state).
If we lose the ACK and resubmit, we will see success but the watch will not
be correctly registered and we won't get notifies.
To fix this, always resubmit the linger op with a new tid. We accomplish
this by re-registering as a linger (i.e., 'registered') if we are not yet
registered. Then the second loop will treat this just like a normal
case of re-registering.
This mirrors a similar fix on the userland ceph.git, commit 5dd68b95, and
ceph bug #2796.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osd_client.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -888,7 +888,9 @@ static void __register_linger_request(st
{
dout("__register_linger_request %p\n", req);
list_add_tail(&req->r_linger_item, &osdc->req_linger);
- list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests);
+ if (req->r_osd)
+ list_add_tail(&req->r_linger_osd,
+ &req->r_osd->o_linger_requests);
}
static void __unregister_linger_request(struct ceph_osd_client *osdc,
@@ -1302,8 +1304,9 @@ static void kick_requests(struct ceph_os
dout("kick_requests %s\n", force_resend ? " (force resend)" : "");
mutex_lock(&osdc->request_mutex);
- for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
+ for (p = rb_first(&osdc->requests); p; ) {
req = rb_entry(p, struct ceph_osd_request, r_node);
+ p = rb_next(p);
err = __map_request(osdc, req, force_resend);
if (err < 0)
continue; /* error */
@@ -1311,10 +1314,23 @@ static void kick_requests(struct ceph_os
dout("%p tid %llu maps to no osd\n", req, req->r_tid);
needmap++; /* request a newer map */
} else if (err > 0) {
- dout("%p tid %llu requeued on osd%d\n", req, req->r_tid,
- req->r_osd ? req->r_osd->o_osd : -1);
- if (!req->r_linger)
+ if (!req->r_linger) {
+ dout("%p tid %llu requeued on osd%d\n", req,
+ req->r_tid,
+ req->r_osd ? req->r_osd->o_osd : -1);
req->r_flags |= CEPH_OSD_FLAG_RETRY;
+ }
+ }
+ if (req->r_linger && list_empty(&req->r_linger_item)) {
+ /*
+ * register as a linger so that we will
+ * re-submit below and get a new tid
+ */
+ dout("%p tid %llu restart on osd%d\n",
+ req, req->r_tid,
+ req->r_osd ? req->r_osd->o_osd : -1);
+ __register_linger_request(osdc, req);
+ __unregister_request(osdc, req);
}
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit dac1e716c60161867a47745bca592987ca3a9cb2)
Change the name of prepare_connect_authorizer(). The next
patch is going to make this function no longer add anything to the
connection's out_kvec, so it will no longer fit the pattern of
the rest of the prepare_connect_*() functions.
In addition, pass the address of a variable that will hold the
authorization protocol to use. Move the assignment of that to the
connection's out_connect structure into prepare_write_connect().
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -653,11 +653,11 @@ static void prepare_write_keepalive(stru
* Connection negotiation.
*/
-static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con)
+static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con,
+ int *auth_proto)
{
void *auth_buf;
int auth_len;
- int auth_protocol;
struct ceph_auth_handshake *auth;
if (!con->ops->get_authorizer) {
@@ -671,8 +671,7 @@ static struct ceph_auth_handshake *prepa
mutex_unlock(&con->mutex);
- auth_protocol = CEPH_AUTH_UNKNOWN;
- auth = con->ops->get_authorizer(con, &auth_protocol, con->auth_retry);
+ auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry);
mutex_lock(&con->mutex);
@@ -686,7 +685,6 @@ static struct ceph_auth_handshake *prepa
con->auth_reply_buf = auth->authorizer_reply_buf;
con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
- con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
con->out_connect.authorizer_len = cpu_to_le32(auth_len);
if (auth_len)
@@ -712,6 +710,7 @@ static int prepare_write_connect(struct
{
unsigned global_seq = get_global_seq(con->msgr, 0);
int proto;
+ int auth_proto;
struct ceph_auth_handshake *auth;
switch (con->peer_name.type) {
@@ -739,9 +738,11 @@ static int prepare_write_connect(struct
con->out_connect.flags = 0;
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
- auth = prepare_connect_authorizer(con);
+ auth_proto = CEPH_AUTH_UNKNOWN;
+ auth = get_connect_authorizer(con, &auth_proto);
if (IS_ERR(auth))
return PTR_ERR(auth);
+ con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
con->out_more = 0;
set_bit(WRITE_PENDING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8c50c817566dfa4581f82373aac39f3e608a7dc8)
Hold the mutex while twiddling all of the state bits to avoid possible
races. While we're here, make not of why we cannot close the socket
directly.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -503,6 +503,7 @@ static void reset_connection(struct ceph
*/
void ceph_con_close(struct ceph_connection *con)
{
+ mutex_lock(&con->mutex);
dout("con_close %p peer %s\n", con,
ceph_pr_addr(&con->peer_addr.in_addr));
clear_bit(NEGOTIATING, &con->state);
@@ -515,11 +516,16 @@ void ceph_con_close(struct ceph_connecti
clear_bit(KEEPALIVE_PENDING, &con->flags);
clear_bit(WRITE_PENDING, &con->flags);
- mutex_lock(&con->mutex);
reset_connection(con);
con->peer_global_seq = 0;
cancel_delayed_work(&con->work);
mutex_unlock(&con->mutex);
+
+ /*
+ * We cannot close the socket directly from here because the
+ * work threads use it without holding the mutex. Instead, let
+ * con_work() do it.
+ */
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_close);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Schmidt <[email protected]>
commit aee77e4accbeb2c86b1d294cd84fec4a12dde3bd upstream.
The r8169 driver currently limits the DMA burst for TX to 1024 bytes. I have
a box where this prevents the interface from using the gigabit line to its full
potential. This patch solves the problem by setting TX_DMA_BURST to unlimited.
The box has an ASRock B75M motherboard with on-board RTL8168evl/8111evl
(XID 0c900880). TSO is enabled.
I used netperf (TCP_STREAM test) to measure the dependency of TX throughput
on MTU. I did it for three different values of TX_DMA_BURST ('5'=512, '6'=1024,
'7'=unlimited). This chart shows the results:
http://michich.fedorapeople.org/r8169/r8169-effects-of-TX_DMA_BURST.png
Interesting points:
- With the current DMA burst limit (1024):
- at the default MTU=1500 I get only 842 Mbit/s.
- when going from small MTU, the performance rises monotonically with
increasing MTU only up to a peak at MTU=1076 (908 MBit/s). Then there's
a sudden drop to 762 MBit/s from which the throughput rises monotonically
again with further MTU increases.
- With a smaller DMA burst limit (512):
- there's a similar peak at MTU=1076 and another one at MTU=564.
- With unlimited DMA burst:
- at the default MTU=1500 I get nice 940 Mbit/s.
- the throughput rises monotonically with increasing MTU with no strange
peaks.
Notice that the peaks occur at MTU sizes that are multiples of the DMA burst
limit plus 52. Why 52? Because:
20 (IP header) + 20 (TCP header) + 12 (TCP options) = 52
The Realtek-provided r8168 driver (v8.032.00) uses unlimited TX DMA burst too,
except for CFG_METHOD_1 where the TX DMA burst is set to 512 bytes.
CFG_METHOD_1 appears to be the oldest MAC version of "RTL8168B/8111B",
i.e. RTL_GIGA_MAC_VER_11 in r8169. Not sure if this MAC version really needs
the smaller burst limit, or if any other versions have similar requirements.
Signed-off-by: Michal Schmidt <[email protected]>
Acked-by: Francois Romieu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/ethernet/realtek/r8169.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -73,7 +73,7 @@
static const int multicast_filter_limit = 32;
#define MAX_READ_REQUEST_SHIFT 12
-#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e6cee71fac27c946a0bbad754dd076e66c4e9dbd)
read_partial() always increases whatever "to" value is supplied by
adding the requested size to it, and that's the only thing it does
with that pointed-to value.
Do that pointer advance in the caller (and then only when the
updated value will be subsequently used), and change the "to"
parameter to be an in-only and non-pointer value.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -992,11 +992,12 @@ static int prepare_read_message(struct c
static int read_partial(struct ceph_connection *con,
- int *to, int size, void *object)
+ int to, int size, void *object)
{
- *to += size;
- while (con->in_base_pos < *to) {
- int left = *to - con->in_base_pos;
+ int end = to + size;
+
+ while (con->in_base_pos < end) {
+ int left = end - con->in_base_pos;
int have = size - left;
int ret = ceph_tcp_recvmsg(con->sock, object + have, left);
if (ret <= 0)
@@ -1017,14 +1018,16 @@ static int read_partial_banner(struct ce
dout("read_partial_banner %p at %d\n", con, con->in_base_pos);
/* peer's banner */
- ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner);
+ ret = read_partial(con, to, strlen(CEPH_BANNER), con->in_banner);
if (ret <= 0)
goto out;
- ret = read_partial(con, &to, sizeof(con->actual_peer_addr),
+ to += strlen(CEPH_BANNER);
+ ret = read_partial(con, to, sizeof(con->actual_peer_addr),
&con->actual_peer_addr);
if (ret <= 0)
goto out;
- ret = read_partial(con, &to, sizeof(con->peer_addr_for_me),
+ to += sizeof(con->actual_peer_addr);
+ ret = read_partial(con, to, sizeof(con->peer_addr_for_me),
&con->peer_addr_for_me);
if (ret <= 0)
goto out;
@@ -1038,10 +1041,11 @@ static int read_partial_connect(struct c
dout("read_partial_connect %p at %d\n", con, con->in_base_pos);
- ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply);
+ ret = read_partial(con, to, sizeof(con->in_reply), &con->in_reply);
if (ret <= 0)
goto out;
- ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len),
+ to += sizeof(con->in_reply);
+ ret = read_partial(con, to, le32_to_cpu(con->in_reply.authorizer_len),
con->auth_reply_buf);
if (ret <= 0)
goto out;
@@ -1491,9 +1495,7 @@ static int process_connect(struct ceph_c
*/
static int read_partial_ack(struct ceph_connection *con)
{
- int to = 0;
-
- return read_partial(con, &to, sizeof(con->in_temp_ack),
+ return read_partial(con, 0, sizeof(con->in_temp_ack),
&con->in_temp_ack);
}
@@ -1638,8 +1640,7 @@ static int read_partial_message(struct c
dout("read_partial_message con %p msg %p\n", con, m);
/* header */
- to = 0;
- ret = read_partial(con, &to, sizeof (con->in_hdr), &con->in_hdr);
+ ret = read_partial(con, 0, sizeof (con->in_hdr), &con->in_hdr);
if (ret <= 0)
return ret;
@@ -1755,7 +1756,7 @@ static int read_partial_message(struct c
/* footer */
to = sizeof (m->hdr);
- ret = read_partial(con, &to, sizeof (m->footer), &m->footer);
+ ret = read_partial(con, to, sizeof (m->footer), &m->footer);
if (ret <= 0)
return ret;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit fbb85a478f6d4cce6942f1c25c6a68ec5b1e7e7f)
It is possible to close a socket that is in the OPENING state. For
example, it can happen if ceph_con_close() is called on the con before
the TCP connection is established. con_work() will come around and shut
down the socket.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -48,17 +48,17 @@
* | ----------------------
* | \
* + con_sock_state_closed() \
- * |\ \
- * | \ \
- * | ----------- \
- * | | CLOSING | socket event; \
- * | ----------- await close \
- * | ^ |
- * | | |
- * | + con_sock_state_closing() |
- * | / \ |
- * | / --------------- |
- * | / \ v
+ * |+--------------------------- \
+ * | \ \ \
+ * | ----------- \ \
+ * | | CLOSING | socket event; \ \
+ * | ----------- await close \ \
+ * | ^ \ |
+ * | | \ |
+ * | + con_sock_state_closing() \ |
+ * | / \ | |
+ * | / --------------- | |
+ * | / \ v v
* | / --------------
* | / -----------------| CONNECTING | socket created, TCP
* | | / -------------- connect initiated
@@ -241,7 +241,8 @@ static void con_sock_state_closed(struct
old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED);
if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED &&
- old_state != CON_SOCK_STATE_CLOSING))
+ old_state != CON_SOCK_STATE_CLOSING &&
+ old_state != CON_SOCK_STATE_CONNECTING))
printk("%s: unexpected old state %d\n", __func__, old_state);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 20581c1faf7b15ae1f8b80c0ec757877b0b53151)
Hold off initializing a monitor client's connection until just
before it gets opened for use.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/mon_client.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -119,6 +119,7 @@ static void __close_session(struct ceph_
dout("__close_session closing mon%d\n", monc->cur_mon);
ceph_con_revoke(&monc->con, monc->m_auth);
ceph_con_close(&monc->con);
+ monc->con.private = NULL;
monc->cur_mon = -1;
monc->pending_auth = 0;
ceph_auth_reset(monc->auth);
@@ -141,9 +142,13 @@ static int __open_session(struct ceph_mo
monc->sub_renew_after = jiffies; /* i.e., expired */
monc->want_next_osdmap = !!monc->want_next_osdmap;
- dout("open_session mon%d opening\n", monc->cur_mon);
+ ceph_con_init(&monc->client->msgr, &monc->con);
+ monc->con.private = monc;
+ monc->con.ops = &mon_con_ops;
monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON;
monc->con.peer_name.num = cpu_to_le64(monc->cur_mon);
+
+ dout("open_session mon%d opening\n", monc->cur_mon);
ceph_con_open(&monc->con,
&monc->monmap->mon_inst[monc->cur_mon].addr);
@@ -760,10 +765,6 @@ int ceph_monc_init(struct ceph_mon_clien
goto out;
/* connection */
- ceph_con_init(&monc->client->msgr, &monc->con);
- monc->con.private = monc;
- monc->con.ops = &mon_con_ops;
-
/* authentication */
monc->auth = ceph_auth_init(cl->options->name,
cl->options->key);
@@ -836,8 +837,6 @@ void ceph_monc_stop(struct ceph_mon_clie
mutex_lock(&monc->mutex);
__close_session(monc);
- monc->con.private = NULL;
-
mutex_unlock(&monc->mutex);
/*
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Safrata <[email protected]>
commit 0658a3366db7e27fa32c12e886230bb58c414c92 upstream.
The use of kfree(serial) in error cases of usb_serial_probe
was invalid - usb_serial structure allocated in create_serial()
gets reference of usb_device that needs to be put, so we need
to use usb_serial_put() instead of simple kfree().
Signed-off-by: Jan Safrata <[email protected]>
Acked-by: Johan Hovold <[email protected]>
Cc: Richard Retanubun <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/usb-serial.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -768,7 +768,7 @@ int usb_serial_probe(struct usb_interfac
if (retval) {
dbg("sub driver rejected device");
- kfree(serial);
+ usb_serial_put(serial);
module_put(type->driver.owner);
return retval;
}
@@ -840,7 +840,7 @@ int usb_serial_probe(struct usb_interfac
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
- kfree(serial);
+ usb_serial_put(serial);
module_put(type->driver.owner);
return -ENODEV;
}
@@ -854,7 +854,7 @@ int usb_serial_probe(struct usb_interfac
if (num_ports == 0) {
dev_err(&interface->dev,
"Generic device with no bulk out, not allowed.\n");
- kfree(serial);
+ usb_serial_put(serial);
module_put(type->driver.owner);
return -EIO;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d1c338a509cea5378df59629ad47382810c38623)
The debugfs directory includes the cluster fsid and our unique global_id.
We need to delay the initialization of the debug entry until we have
learned both the fsid and our global_id from the monitor or else the
second client can't create its debugfs entry and will fail (and multiple
client instances aren't properly reflected in debugfs).
Reported by: Yan, Zheng <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/debugfs.c | 1
net/ceph/ceph_common.c | 1
net/ceph/debugfs.c | 4 +++
net/ceph/mon_client.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-----
4 files changed, 51 insertions(+), 6 deletions(-)
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_
int err = -ENOMEM;
dout("ceph_fs_debugfs_init\n");
+ BUG_ON(!fsc->client->debugfs_dir);
fsc->debugfs_congestion_kb =
debugfs_create_file("writeback_congestion_kb",
0600,
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -83,7 +83,6 @@ int ceph_check_fsid(struct ceph_client *
return -1;
}
} else {
- pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
memcpy(&client->fsid, fsid, sizeof(*fsid));
}
return 0;
--- a/net/ceph/debugfs.c
+++ b/net/ceph/debugfs.c
@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph
snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,
client->monc.auth->global_id);
+ dout("ceph_debugfs_client_init %p %s\n", client, name);
+
+ BUG_ON(client->debugfs_dir);
client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);
if (!client->debugfs_dir)
goto out;
@@ -234,6 +237,7 @@ out:
void ceph_debugfs_client_cleanup(struct ceph_client *client)
{
+ dout("ceph_debugfs_client_cleanup %p\n", client);
debugfs_remove(client->debugfs_osdmap);
debugfs_remove(client->debugfs_monmap);
debugfs_remove(client->osdc.debugfs_file);
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -311,6 +311,17 @@ int ceph_monc_open_session(struct ceph_m
EXPORT_SYMBOL(ceph_monc_open_session);
/*
+ * We require the fsid and global_id in order to initialize our
+ * debugfs dir.
+ */
+static bool have_debugfs_info(struct ceph_mon_client *monc)
+{
+ dout("have_debugfs_info fsid %d globalid %lld\n",
+ (int)monc->client->have_fsid, monc->auth->global_id);
+ return monc->client->have_fsid && monc->auth->global_id > 0;
+}
+
+/*
* The monitor responds with mount ack indicate mount success. The
* included client ticket allows the client to talk to MDSs and OSDs.
*/
@@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct
struct ceph_client *client = monc->client;
struct ceph_monmap *monmap = NULL, *old = monc->monmap;
void *p, *end;
+ int had_debugfs_info, init_debugfs = 0;
mutex_lock(&monc->mutex);
+ had_debugfs_info = have_debugfs_info(monc);
+
dout("handle_monmap\n");
p = msg->front.iov_base;
end = p + msg->front.iov_len;
@@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct
if (!client->have_fsid) {
client->have_fsid = true;
+ if (!had_debugfs_info && have_debugfs_info(monc)) {
+ pr_info("client%lld fsid %pU\n",
+ ceph_client_id(monc->client),
+ &monc->client->fsid);
+ init_debugfs = 1;
+ }
mutex_unlock(&monc->mutex);
- /*
- * do debugfs initialization without mutex to avoid
- * creating a locking dependency
- */
- ceph_debugfs_client_init(client);
+
+ if (init_debugfs) {
+ /*
+ * do debugfs initialization without mutex to avoid
+ * creating a locking dependency
+ */
+ ceph_debugfs_client_init(monc->client);
+ }
+
goto out_unlocked;
}
out:
@@ -865,8 +889,10 @@ static void handle_auth_reply(struct cep
{
int ret;
int was_auth = 0;
+ int had_debugfs_info, init_debugfs = 0;
mutex_lock(&monc->mutex);
+ had_debugfs_info = have_debugfs_info(monc);
if (monc->auth->ops)
was_auth = monc->auth->ops->is_authenticated(monc->auth);
monc->pending_auth = 0;
@@ -889,7 +915,22 @@ static void handle_auth_reply(struct cep
__send_subscribe(monc);
__resend_generic_request(monc);
}
+
+ if (!had_debugfs_info && have_debugfs_info(monc)) {
+ pr_info("client%lld fsid %pU\n",
+ ceph_client_id(monc->client),
+ &monc->client->fsid);
+ init_debugfs = 1;
+ }
mutex_unlock(&monc->mutex);
+
+ if (init_debugfs) {
+ /*
+ * do debugfs initialization without mutex to avoid
+ * creating a locking dependency
+ */
+ ceph_debugfs_client_init(monc->client);
+ }
}
static int __validate_auth(struct ceph_mon_client *monc)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 065a68f9167e20f321a62d044cb2c3024393d455)
>From Al Viro <[email protected]>
Al Viro noticed that we were using a non-cpu-encoded value in
a switch statement in osd_req_encode_op(). The result would
clearly not work correctly on a big-endian machine.
Signed-off-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osd_client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -278,7 +278,7 @@ static void osd_req_encode_op(struct cep
{
dst->op = cpu_to_le16(src->op);
- switch (dst->op) {
+ switch (src->op) {
case CEPH_OSD_OP_READ:
case CEPH_OSD_OP_WRITE:
dst->extent.offset =
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit a1f4895be8bf1ba56c2306b058f51619e9b0e8f8)
If we get a map that doesn't make sense, error out or ignore the badness
instead of BUGging out. This reflects the ceph.git commits
9895f0bff7dc68e9b49b572613d242315fb11b6c and
8ded26472058d5205803f244c2f33cb6cb10de79.
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/crush/mapper.c | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
--- a/net/ceph/crush/mapper.c
+++ b/net/ceph/crush/mapper.c
@@ -152,8 +152,8 @@ static int bucket_list_choose(struct cru
return bucket->h.items[i];
}
- BUG_ON(1);
- return 0;
+ dprintk("bad list sums for bucket %d\n", bucket->h.id);
+ return bucket->h.items[0];
}
@@ -239,6 +239,7 @@ static int bucket_straw_choose(struct cr
static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
{
dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r);
+ BUG_ON(in->size == 0);
switch (in->alg) {
case CRUSH_BUCKET_UNIFORM:
return bucket_uniform_choose((struct crush_bucket_uniform *)in,
@@ -253,7 +254,7 @@ static int crush_bucket_choose(struct cr
return bucket_straw_choose((struct crush_bucket_straw *)in,
x, r);
default:
- BUG_ON(1);
+ dprintk("unknown bucket %d alg %d\n", in->id, in->alg);
return in->items[0];
}
}
@@ -354,7 +355,11 @@ static int crush_choose(const struct cru
item = bucket_perm_choose(in, x, r);
else
item = crush_bucket_choose(in, x, r);
- BUG_ON(item >= map->max_devices);
+ if (item >= map->max_devices) {
+ dprintk(" bad item %d\n", item);
+ skip_rep = 1;
+ break;
+ }
/* desired type? */
if (item < 0)
@@ -365,8 +370,12 @@ static int crush_choose(const struct cru
/* keep going? */
if (itemtype != type) {
- BUG_ON(item >= 0 ||
- (-1-item) >= map->max_buckets);
+ if (item >= 0 ||
+ (-1-item) >= map->max_buckets) {
+ dprintk(" bad item type %d\n", type);
+ skip_rep = 1;
+ break;
+ }
in = map->buckets[-1-item];
retry_bucket = 1;
continue;
@@ -478,7 +487,10 @@ int crush_do_rule(const struct crush_map
int numrep;
int firstn;
- BUG_ON(ruleno >= map->max_rules);
+ if ((__u32)ruleno >= map->max_rules) {
+ dprintk(" bad ruleno %d\n", ruleno);
+ return 0;
+ }
rule = map->rules[ruleno];
result_len = 0;
@@ -528,7 +540,8 @@ int crush_do_rule(const struct crush_map
firstn = 1;
case CRUSH_RULE_CHOOSE_LEAF_INDEP:
case CRUSH_RULE_CHOOSE_INDEP:
- BUG_ON(wsize == 0);
+ if (wsize == 0)
+ break;
recurse_to_leaf =
rule->steps[step].op ==
@@ -597,7 +610,9 @@ int crush_do_rule(const struct crush_map
break;
default:
- BUG_ON(1);
+ dprintk(" unknown op %d at step %d\n",
+ curstep->op, step);
+ break;
}
}
return result_len;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8b12d47b80c7a34dffdd98244d99316db490ec58)
Move various types from int -> __u32 (or similar), and add const as
appropriate.
This reflects changes that have been present in the userland implementation
for some time.
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/crush/crush.h | 2 +-
include/linux/crush/mapper.h | 6 +++---
net/ceph/crush/crush.c | 8 ++++----
net/ceph/crush/mapper.c | 31 ++++++++++++++++---------------
4 files changed, 24 insertions(+), 23 deletions(-)
--- a/include/linux/crush/crush.h
+++ b/include/linux/crush/crush.h
@@ -168,7 +168,7 @@ struct crush_map {
/* crush.c */
-extern int crush_get_bucket_item_weight(struct crush_bucket *b, int pos);
+extern int crush_get_bucket_item_weight(const struct crush_bucket *b, int pos);
extern void crush_calc_parents(struct crush_map *map);
extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b);
extern void crush_destroy_bucket_list(struct crush_bucket_list *b);
--- a/include/linux/crush/mapper.h
+++ b/include/linux/crush/mapper.h
@@ -10,11 +10,11 @@
#include "crush.h"
-extern int crush_find_rule(struct crush_map *map, int pool, int type, int size);
-extern int crush_do_rule(struct crush_map *map,
+extern int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size);
+extern int crush_do_rule(const struct crush_map *map,
int ruleno,
int x, int *result, int result_max,
int forcefeed, /* -1 for none */
- __u32 *weights);
+ const __u32 *weights);
#endif
--- a/net/ceph/crush/crush.c
+++ b/net/ceph/crush/crush.c
@@ -26,9 +26,9 @@ const char *crush_bucket_alg_name(int al
* @b: bucket pointer
* @p: item index in bucket
*/
-int crush_get_bucket_item_weight(struct crush_bucket *b, int p)
+int crush_get_bucket_item_weight(const struct crush_bucket *b, int p)
{
- if (p >= b->size)
+ if ((__u32)p >= b->size)
return 0;
switch (b->alg) {
@@ -124,10 +124,9 @@ void crush_destroy_bucket(struct crush_b
*/
void crush_destroy(struct crush_map *map)
{
- int b;
-
/* buckets */
if (map->buckets) {
+ __s32 b;
for (b = 0; b < map->max_buckets; b++) {
if (map->buckets[b] == NULL)
continue;
@@ -138,6 +137,7 @@ void crush_destroy(struct crush_map *map
/* rules */
if (map->rules) {
+ __u32 b;
for (b = 0; b < map->max_rules; b++)
kfree(map->rules[b]);
kfree(map->rules);
--- a/net/ceph/crush/mapper.c
+++ b/net/ceph/crush/mapper.c
@@ -32,9 +32,9 @@
* @type: storage ruleset type (user defined)
* @size: output set size
*/
-int crush_find_rule(struct crush_map *map, int ruleset, int type, int size)
+int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size)
{
- int i;
+ __u32 i;
for (i = 0; i < map->max_rules; i++) {
if (map->rules[i] &&
@@ -72,7 +72,7 @@ static int bucket_perm_choose(struct cru
unsigned i, s;
/* start a new permutation if @x has changed */
- if (bucket->perm_x != x || bucket->perm_n == 0) {
+ if (bucket->perm_x != (__u32)x || bucket->perm_n == 0) {
dprintk("bucket %d new x=%d\n", bucket->id, x);
bucket->perm_x = x;
@@ -219,7 +219,7 @@ static int bucket_tree_choose(struct cru
static int bucket_straw_choose(struct crush_bucket_straw *bucket,
int x, int r)
{
- int i;
+ __u32 i;
int high = 0;
__u64 high_draw = 0;
__u64 draw;
@@ -262,7 +262,7 @@ static int crush_bucket_choose(struct cr
* true if device is marked "out" (failed, fully offloaded)
* of the cluster
*/
-static int is_out(struct crush_map *map, __u32 *weight, int item, int x)
+static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x)
{
if (weight[item] >= 0x10000)
return 0;
@@ -287,16 +287,16 @@ static int is_out(struct crush_map *map,
* @recurse_to_leaf: true if we want one device under each item of given type
* @out2: second output vector for leaf items (if @recurse_to_leaf)
*/
-static int crush_choose(struct crush_map *map,
+static int crush_choose(const struct crush_map *map,
struct crush_bucket *bucket,
- __u32 *weight,
+ const __u32 *weight,
int x, int numrep, int type,
int *out, int outpos,
int firstn, int recurse_to_leaf,
int *out2)
{
int rep;
- int ftotal, flocal;
+ unsigned int ftotal, flocal;
int retry_descent, retry_bucket, skip_rep;
struct crush_bucket *in = bucket;
int r;
@@ -304,7 +304,7 @@ static int crush_choose(struct crush_map
int item = 0;
int itemtype;
int collide, reject;
- const int orig_tries = 5; /* attempts before we fall back to search */
+ const unsigned int orig_tries = 5; /* attempts before we fall back to search */
dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "",
bucket->id, x, outpos, numrep);
@@ -325,7 +325,7 @@ static int crush_choose(struct crush_map
r = rep;
if (in->alg == CRUSH_BUCKET_UNIFORM) {
/* be careful */
- if (firstn || numrep >= in->size)
+ if (firstn || (__u32)numrep >= in->size)
/* r' = r + f_total */
r += ftotal;
else if (in->size % numrep == 0)
@@ -425,7 +425,7 @@ reject:
/* else give up */
skip_rep = 1;
dprintk(" reject %d collide %d "
- "ftotal %d flocal %d\n",
+ "ftotal %u flocal %u\n",
reject, collide, ftotal,
flocal);
}
@@ -456,9 +456,9 @@ reject:
* @result_max: maximum result size
* @force: force initial replica choice; -1 for none
*/
-int crush_do_rule(struct crush_map *map,
+int crush_do_rule(const struct crush_map *map,
int ruleno, int x, int *result, int result_max,
- int force, __u32 *weight)
+ int force, const __u32 *weight)
{
int result_len;
int force_context[CRUSH_MAX_DEPTH];
@@ -473,7 +473,7 @@ int crush_do_rule(struct crush_map *map,
int osize;
int *tmp;
struct crush_rule *rule;
- int step;
+ __u32 step;
int i, j;
int numrep;
int firstn;
@@ -488,7 +488,8 @@ int crush_do_rule(struct crush_map *map,
/*
* determine hierarchical context of force, if any. note
* that this may or may not correspond to the specific types
- * referenced by the crush rule.
+ * referenced by the crush rule. it will also only affect
+ * the first descent (TAKE).
*/
if (force >= 0 &&
force < map->max_devices &&
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 729796be9190f57ca40ccca315e8ad34a1eb8fef)
Change prepare_connect_authorizer() so it returns a pointer (or
pointer-coded error).
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -653,7 +653,7 @@ static void prepare_write_keepalive(stru
* Connection negotiation.
*/
-static int prepare_connect_authorizer(struct ceph_connection *con)
+static struct ceph_auth_handshake *prepare_connect_authorizer(struct ceph_connection *con)
{
void *auth_buf;
int auth_len;
@@ -664,7 +664,7 @@ static int prepare_connect_authorizer(st
con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
con->out_connect.authorizer_len = 0;
- return 0;
+ return NULL;
}
/* Can't hold the mutex while getting authorizer */
@@ -677,9 +677,9 @@ static int prepare_connect_authorizer(st
mutex_lock(&con->mutex);
if (IS_ERR(auth))
- return PTR_ERR(auth);
+ return auth;
if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
- return -EAGAIN;
+ return ERR_PTR(-EAGAIN);
auth_buf = auth->authorizer_buf;
auth_len = auth->authorizer_buf_len;
@@ -692,7 +692,7 @@ static int prepare_connect_authorizer(st
if (auth_len)
ceph_con_out_kvec_add(con, auth_len, auth_buf);
- return 0;
+ return auth;
}
/*
@@ -712,7 +712,7 @@ static int prepare_write_connect(struct
{
unsigned global_seq = get_global_seq(con->msgr, 0);
int proto;
- int ret;
+ struct ceph_auth_handshake *auth;
switch (con->peer_name.type) {
case CEPH_ENTITY_TYPE_MON:
@@ -739,9 +739,9 @@ static int prepare_write_connect(struct
con->out_connect.flags = 0;
ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect);
- ret = prepare_connect_authorizer(con);
- if (ret)
- return ret;
+ auth = prepare_connect_authorizer(con);
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
con->out_more = 0;
set_bit(WRITE_PENDING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Pirko <[email protected]>
[ Upstream commit a652208e0b52c190e57f2a075ffb5e897fe31c3b ]
Check (ha->addr == dev->dev_addr) is always true because dev_addr_init()
sets this. Correct the check to behave properly on addr removal.
Signed-off-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/core/dev_addr_lists.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -308,7 +308,8 @@ int dev_addr_del(struct net_device *dev,
*/
ha = list_first_entry(&dev->dev_addrs.list,
struct netdev_hw_addr, list);
- if (ha->addr == dev->dev_addr && ha->refcount == 1)
+ if (!memcmp(ha->addr, addr, dev->addr_len) &&
+ ha->type == addr_type && ha->refcount == 1)
return -ENOENT;
err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xi Wang <[email protected]>
(cherry picked from commit a5506049500b30dbc5edb4d07a3577477c1f3643)
On 32-bit systems, a large `pglen' would overflow `pglen*sizeof(u32)'
and bypass the check ceph_decode_need(p, end, pglen*sizeof(u32), bad).
It would also overflow the subsequent kmalloc() size, leading to
out-of-bounds write.
Signed-off-by: Xi Wang <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osdmap.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -900,6 +900,10 @@ struct ceph_osdmap *osdmap_apply_increme
(void) __remove_pg_mapping(&map->pg_temp, pgid);
/* insert */
+ if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) {
+ err = -EINVAL;
+ goto bad;
+ }
pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
if (!pg) {
err = -ENOMEM;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jim Schutt <[email protected]>
(cherry picked from commit 6d4221b53707486dfad3f5bfe568d2ce7f4c9863)
Because the Ceph client messenger uses a non-blocking connect, it is
possible for the sending of the client banner to race with the
arrival of the banner sent by the peer.
When ceph_sock_state_change() notices the connect has completed, it
schedules work to process the socket via con_work(). During this
time the peer is writing its banner, and arrival of the peer banner
races with con_work().
If con_work() calls try_read() before the peer banner arrives, there
is nothing for it to do, after which con_work() calls try_write() to
send the client's banner. In this case Ceph's protocol negotiation
can complete succesfully.
The server-side messenger immediately sends its banner and addresses
after accepting a connect request, *before* actually attempting to
read or verify the banner from the client. As a result, it is
possible for the banner from the server to arrive before con_work()
calls try_read(). If that happens, try_read() will read the banner
and prepare protocol negotiation info via prepare_write_connect().
prepare_write_connect() calls con_out_kvec_reset(), which discards
the as-yet-unsent client banner. Next, con_work() calls
try_write(), which sends the protocol negotiation info rather than
the banner that the peer is expecting.
The result is that the peer sees an invalid banner, and the client
reports "negotiation failed".
Fix this by moving con_out_kvec_reset() out of
prepare_write_connect() to its callers at all locations except the
one where the banner might still need to be sent.
[[email protected]: added note about server-side behavior]
Signed-off-by: Jim Schutt <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -911,7 +911,6 @@ static int prepare_write_connect(struct
con->out_connect.authorizer_len = auth ?
cpu_to_le32(auth->authorizer_buf_len) : 0;
- con_out_kvec_reset(con);
con_out_kvec_add(con, sizeof (con->out_connect),
&con->out_connect);
if (auth && auth->authorizer_buf_len)
@@ -1553,6 +1552,7 @@ static int process_connect(struct ceph_c
return -1;
}
con->auth_retry = 1;
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1573,6 +1573,7 @@ static int process_connect(struct ceph_c
ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1597,6 +1598,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->out_connect.connect_seq),
le32_to_cpu(con->in_reply.connect_seq));
con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -1613,6 +1615,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_reply.global_seq));
get_global_seq(con->msgr,
le32_to_cpu(con->in_reply.global_seq));
+ con_out_kvec_reset(con);
ret = prepare_write_connect(con);
if (ret < 0)
return ret;
@@ -2131,7 +2134,11 @@ more:
BUG_ON(con->state != CON_STATE_CONNECTING);
con->state = CON_STATE_NEGOTIATING;
- /* Banner is good, exchange connection info */
+ /*
+ * Received banner is good, exchange connection info.
+ * Do not reset out_kvec, as sending our banner raced
+ * with receiving peer banner after connect completed.
+ */
ret = prepare_write_connect(con);
if (ret < 0)
goto out;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Misael Lopez Cruz <[email protected]>
commit 445632ad6dda42f4d3f9df2569a852ca0d4ea608 upstream.
DAPM shutdown incorrectly uses "list" field of codec struct while
iterating over probed components (codec_dev_list). "list" field
refers to codecs registered in the system, "card_list" field is
used for probed components.
Signed-off-by: Misael Lopez Cruz <[email protected]>
Signed-off-by: Liam Girdwood <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/soc/soc-dapm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -3253,7 +3253,7 @@ void snd_soc_dapm_shutdown(struct snd_so
{
struct snd_soc_codec *codec;
- list_for_each_entry(codec, &card->codec_dev_list, list) {
+ list_for_each_entry(codec, &card->codec_dev_list, card_list) {
soc_dapm_shutdown_codec(&codec->dapm);
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
snd_soc_dapm_set_bias_level(&codec->dapm,
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 2e8cb10063820af7ed7638e3fd9013eee21266e7)
If the state is CLOSED or OPENING, we shouldn't have a socket.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2284,15 +2284,15 @@ restart:
dout("con_work %p STANDBY\n", con);
goto done;
}
- if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */
- dout("con_work CLOSED\n");
- con_close_socket(con);
+ if (test_bit(CLOSED, &con->state)) {
+ dout("con_work %p CLOSED\n", con);
+ BUG_ON(con->sock);
goto done;
}
if (test_and_clear_bit(OPENING, &con->state)) {
/* reopen w/ new peer */
dout("con_work OPENING\n");
- con_close_socket(con);
+ BUG_ON(con->sock);
}
ret = try_read(con);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 5b3761954dac2d1393beef8210eb8cee81d16b8d upstream.
In via_auto_fill_adc_nids(), the parser tries to fill dac_nids[] at
the point of the current line-out (i). When no valid path is found
for this output, this results in dac = 0, thus it creates a hole in
dac_nids[]. This confuses is_empty_dac() and trims the detected DAC
in later reference.
This patch fixes the bug by appending DAC properly to dac_nids[] in
via_auto_fill_adc_nids().
Reported-by: Massimo Del Fedele <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_via.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1868,11 +1868,11 @@ static int via_auto_fill_dac_nids(struct
{
struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, dac_num;
+ int i;
hda_nid_t nid;
+ spec->multiout.num_dacs = 0;
spec->multiout.dac_nids = spec->private_dac_nids;
- dac_num = 0;
for (i = 0; i < cfg->line_outs; i++) {
hda_nid_t dac = 0;
nid = cfg->line_out_pins[i];
@@ -1883,16 +1883,13 @@ static int via_auto_fill_dac_nids(struct
if (!i && parse_output_path(codec, nid, dac, 1,
&spec->out_mix_path))
dac = spec->out_mix_path.path[0];
- if (dac) {
- spec->private_dac_nids[i] = dac;
- dac_num++;
- }
+ if (dac)
+ spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
}
if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
spec->out_path[0] = spec->out_mix_path;
spec->out_mix_path.depth = 0;
}
- spec->multiout.num_dacs = dac_num;
return 0;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit d65c9e0b9eb43d14ece9dd843506ccba06162ee7)
When a TCP_CLOSE or TCP_CLOSE_WAIT event occurs, the SOCK_CLOSED
connection flag bit is set, and if it had not been previously set
queue_con() is called to ensure con_work() will get a chance to
handle the changed state.
con_work() atomically checks--and if set, clears--the SOCK_CLOSED
bit if it was set. This means that even if the bit were set
repeatedly, the related processing in con_work() only gets called
once per transition of the bit from 0 to 1.
What's important then is that we ensure con_work() gets called *at
least* once when a socket close event occurs, not that it gets
called *exactly* once.
The work queue mechanism already takes care of queueing work
only if it is not already queued, so there's no need for us
to call queue_con() conditionally.
So this patch just makes it so the SOCK_CLOSED flag gets set
unconditionally in ceph_sock_state_change().
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -261,8 +261,8 @@ static void ceph_sock_state_change(struc
case TCP_CLOSE_WAIT:
dout("%s TCP_CLOSE_WAIT\n", __func__);
con_sock_state_closing(con);
- if (!test_and_set_bit(SOCK_CLOSED, &con->flags))
- queue_con(con);
+ set_bit(SOCK_CLOSED, &con->flags);
+ queue_con(con);
break;
case TCP_ESTABLISHED:
dout("%s TCP_ESTABLISHED\n", __func__);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Keller <[email protected]>
commit 87f4d7c1d36f44b0822053b7e5dedc31fdd0ab99 upstream.
This patch updates the adjfreq callback description to include a note that the
delta in ppb is always relative to the base frequency, and not to the current
frequency of the hardware clock.
Signed-off-by: Jacob Keller <[email protected]>
CC: Richard Cochran <[email protected]>
CC: John Stultz <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ptp_clock_kernel.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -50,7 +50,8 @@ struct ptp_clock_request {
* clock operations
*
* @adjfreq: Adjusts the frequency of the hardware clock.
- * parameter delta: Desired period change in parts per billion.
+ * parameter delta: Desired frequency offset from nominal frequency
+ * in parts per billion
*
* @adjtime: Shifts the time of the hardware clock.
* parameter delta: Desired change in nanoseconds.
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e5e372da9a469dfe3ece40277090a7056c566838)
The ceph connection state "DEAD" is never set and is therefore not
needed. Eliminate it.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 1 -
net/ceph/messenger.c | 6 ------
2 files changed, 7 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -119,7 +119,6 @@ struct ceph_msg_pos {
#define CLOSED 10 /* we've closed the connection */
#define SOCK_CLOSED 11 /* socket state changed to closed */
#define OPENING 13 /* open connection w/ (possibly new) peer */
-#define DEAD 14 /* dead, about to kfree */
#define BACKOFF 15
/*
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2091,12 +2091,6 @@ bad_tag:
*/
static void queue_con(struct ceph_connection *con)
{
- if (test_bit(DEAD, &con->state)) {
- dout("queue_con %p ignoring: DEAD\n",
- con);
- return;
- }
-
if (!con->ops->get(con)) {
dout("queue_con %p ref count 0\n", con);
return;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Yan, Zheng" <[email protected]>
(cherry picked from commit f9f9a1904467816452fc70740165030e84c2c659)
ceph_snap_context->snaps is an u64 array
Signed-off-by: Zheng Yan <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/block/rbd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -497,7 +497,7 @@ static int rbd_header_from_disk(struct r
snap_count = le32_to_cpu(ondisk->snap_count);
header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
- snap_count * sizeof (*ondisk),
+ snap_count * sizeof(u64),
gfp_flags);
if (!header->snapc)
return -ENOMEM;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit 05193639ca977cc889668718adb38db6d585045b upstream.
This is another variant of iMac 9,1 with a different codec SSID.
Reported-and-tested-by: Everaldo Canuto <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_realtek.c | 1 +
1 file changed, 1 insertion(+)
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -5458,6 +5458,7 @@ static const struct snd_pci_quirk alc882
SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 572c588edadaa3da3992bd8a0fed830bbcc861f8)
If a message has a non-null bio pointer, its bio_iter field is
initialized in write_partial_msg_pages() if this has not been done
already. This is really a one-time setup operation for sending a
message's (bio) data, so move that initialization code into
prepare_write_message_data() which serves that purpose.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -603,6 +603,10 @@ static void prepare_write_message_data(s
con->out_msg_pos.page_pos = msg->page_alignment;
else
con->out_msg_pos.page_pos = 0;
+#ifdef CONFIG_BLOCK
+ if (msg->bio && !msg->bio_iter)
+ init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
+#endif
con->out_msg_pos.data_pos = 0;
con->out_msg_pos.did_page_crc = false;
con->out_more = 1; /* data + footer will follow */
@@ -942,11 +946,6 @@ static int write_partial_msg_pages(struc
con, msg, con->out_msg_pos.page, msg->nr_pages,
con->out_msg_pos.page_pos);
-#ifdef CONFIG_BLOCK
- if (msg->bio && !msg->bio_iter)
- init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
-#endif
-
while (data_len > con->out_msg_pos.data_pos) {
struct page *page = NULL;
int max_write = PAGE_SIZE;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 92ce034b5a740046cc643a21ea21eaad589e0043)
There are essentially two types of ceph messages: incoming and
outgoing. Outgoing messages are always allocated via ceph_msg_new(),
and at the time of their allocation they are not associated with any
particular connection. Incoming messages are always allocated via
ceph_con_in_msg_alloc(), and they are initially associated with the
connection from which incoming data will be placed into the message.
When an outgoing message gets sent, it becomes associated with a
connection and remains that way until the message is successfully
sent. The association of an incoming message goes away at the point
it is sent to an upper layer via a con->ops->dispatch method.
This patch implements reference counting for all ceph messages, such
that every message holds a reference (and a pointer) to a connection
if and only if it is associated with that connection (as described
above).
For background, here is an explanation of the ceph message
lifecycle, emphasizing when an association exists between a message
and a connection.
Outgoing Messages
An outgoing message is "owned" by its allocator, from the time it is
allocated in ceph_msg_new() up to the point it gets queued for
sending in ceph_con_send(). Prior to that point the message's
msg->con pointer is null; at the point it is queued for sending its
message pointer is assigned to refer to the connection. At that
time the message is inserted into a connection's out_queue list.
When a message on the out_queue list has been sent to the socket
layer to be put on the wire, it is transferred out of that list and
into the connection's out_sent list. At that point it is still owned
by the connection, and will remain so until an acknowledgement is
received from the recipient that indicates the message was
successfully transferred. When such an acknowledgement is received
(in process_ack()), the message is removed from its list (in
ceph_msg_remove()), at which point it is no longer associated with
the connection.
So basically, any time a message is on one of a connection's lists,
it is associated with that connection. Reference counting outgoing
messages can thus be done at the points a message is added to the
out_queue (in ceph_con_send()) and the point it is removed from
either its two lists (in ceph_msg_remove())--at which point its
connection pointer becomes null.
Incoming Messages
When an incoming message on a connection is getting read (in
read_partial_message()) and there is no message in con->in_msg,
a new one is allocated using ceph_con_in_msg_alloc(). At that
point the message is associated with the connection. Once that
message has been completely and successfully read, it is passed to
upper layer code using the connection's con->ops->dispatch method.
At that point the association between the message and the connection
no longer exists.
Reference counting of connections for incoming messages can be done
by taking a reference to the connection when the message gets
allocated, and releasing that reference when it gets handed off
using the dispatch method.
We should never fail to get a connection reference for a
message--the since the caller should already hold one.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -415,6 +415,7 @@ static void ceph_msg_remove(struct ceph_
{
list_del_init(&msg->list_head);
BUG_ON(msg->con == NULL);
+ ceph_con_put(msg->con);
msg->con = NULL;
ceph_msg_put(msg);
@@ -440,6 +441,7 @@ static void reset_connection(struct ceph
con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
+ ceph_con_put(con->in_msg->con);
}
con->connect_seq = 0;
@@ -1918,6 +1920,7 @@ static void process_message(struct ceph_
con->in_msg->con = NULL;
msg = con->in_msg;
con->in_msg = NULL;
+ ceph_con_put(con);
/* if first message, set peer_name */
if (con->peer_name.type == 0)
@@ -2279,6 +2282,7 @@ static void ceph_fault(struct ceph_conne
con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
+ ceph_con_put(con);
}
/* Requeue anything that hasn't been acked */
@@ -2395,8 +2399,11 @@ void ceph_con_send(struct ceph_connectio
/* queue */
mutex_lock(&con->mutex);
+
BUG_ON(msg->con != NULL);
- msg->con = con;
+ msg->con = ceph_con_get(con);
+ BUG_ON(msg->con == NULL);
+
BUG_ON(!list_empty(&msg->list_head));
list_add_tail(&msg->list_head, &con->out_queue);
dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg,
@@ -2425,10 +2432,11 @@ void ceph_con_revoke(struct ceph_connect
dout("%s %p msg %p - was on queue\n", __func__, con, msg);
list_del_init(&msg->list_head);
BUG_ON(msg->con == NULL);
+ ceph_con_put(msg->con);
msg->con = NULL;
+ msg->hdr.seq = 0;
ceph_msg_put(msg);
- msg->hdr.seq = 0;
}
if (con->out_msg == msg) {
dout("%s %p msg %p - was sending\n", __func__, con, msg);
@@ -2437,8 +2445,9 @@ void ceph_con_revoke(struct ceph_connect
con->out_skip = con->out_kvec_bytes;
con->out_kvec_is_msg = false;
}
- ceph_msg_put(msg);
msg->hdr.seq = 0;
+
+ ceph_msg_put(msg);
}
mutex_unlock(&con->mutex);
}
@@ -2622,8 +2631,10 @@ static bool ceph_con_in_msg_alloc(struct
mutex_unlock(&con->mutex);
con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
mutex_lock(&con->mutex);
- if (con->in_msg)
- con->in_msg->con = con;
+ if (con->in_msg) {
+ con->in_msg->con = ceph_con_get(con);
+ BUG_ON(con->in_msg->con == NULL);
+ }
if (skip)
con->in_msg = NULL;
@@ -2637,7 +2648,8 @@ static bool ceph_con_in_msg_alloc(struct
type, front_len);
return false;
}
- con->in_msg->con = con;
+ con->in_msg->con = ceph_con_get(con);
+ BUG_ON(con->in_msg->con == NULL);
con->in_msg->page_alignment = le16_to_cpu(hdr->data_off);
}
memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
commit 36960e440ccf94349c09fb944930d3bfe4bc473f upstream.
The userspace cifs.idmap program generally works with the wbclient libs
to generate binary SIDs in userspace. That program defines the struct
that holds these values as having a max of 15 subauthorities. The kernel
idmapping code however limits that value to 5.
When the kernel copies those values around though, it doesn't sanity
check the num_subauths value handed back from userspace or from the
server. It's possible therefore for userspace to hand us back a bogus
num_subauths value (or one that's valid, but greater than 5) that could
cause the kernel to walk off the end of the cifs_sid->sub_auths array.
Fix this by defining a new routine for copying sids and using that in
all of the places that copy it. If we end up with a sid that's longer
than expected then this approach will just lop off the "extra" subauths,
but that's basically what the code does today already. Better approaches
might be to fix this code to reject SIDs with >5 subauths, or fix it
to handle the subauths array dynamically.
At the same time, change the kernel to check the length of the data
returned by userspace. If it's shorter than struct cifs_sid, reject it
and return -EIO. If that happens we'll end up with fields that are
basically uninitialized.
Long term, it might make sense to redefine cifs_sid using a flexarray at
the end, to allow for variable-length subauth lists, and teach the code
to handle the case where the subauths array being passed in from
userspace is shorter than 5 elements.
Note too, that I don't consider this a security issue since you'd need
a compromised cifs.idmap program. If you have that, you can do all sorts
of nefarious stuff. Still, this is probably reasonable for stable.
Reviewed-by: Shirish Pargaonkar <[email protected]>
Signed-off-by: Jeff Layton <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/cifs/cifsacl.c | 49 ++++++++++++++++++++-----------------------------
1 file changed, 20 insertions(+), 29 deletions(-)
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char
}
static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+ memcpy(dst, src, sizeof(*dst));
+ dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
+}
+
+static void
id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
struct cifs_sid_id **psidid, char *typestr)
{
@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struc
}
}
- memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
+ cifs_copy_sid(&(*psidid)->sid, sidptr);
(*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
(*psidid)->refcount = 0;
@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtyp
* any fields of the node after a reference is put .
*/
if (test_bit(SID_ID_MAPPED, &psidid->state)) {
- memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+ cifs_copy_sid(ssid, &psidid->sid);
psidid->time = jiffies; /* update ts for accessing */
goto id_sid_out;
}
@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtyp
if (IS_ERR(sidkey)) {
rc = -EINVAL;
cFYI(1, "%s: Can't map and id to a SID", __func__);
+ } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
+ rc = -EIO;
+ cFYI(1, "%s: Downcall contained malformed key "
+ "(datalen=%hu)", __func__, sidkey->datalen);
} else {
lsid = (struct cifs_sid *)sidkey->payload.data;
- memcpy(&psidid->sid, lsid,
- sidkey->datalen < sizeof(struct cifs_sid) ?
- sidkey->datalen : sizeof(struct cifs_sid));
- memcpy(ssid, &psidid->sid,
- sidkey->datalen < sizeof(struct cifs_sid) ?
- sidkey->datalen : sizeof(struct cifs_sid));
+ cifs_copy_sid(&psidid->sid, lsid);
+ cifs_copy_sid(ssid, &psidid->sid);
set_bit(SID_ID_MAPPED, &psidid->state);
key_put(sidkey);
kfree(psidid->sidstr);
@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtyp
return rc;
}
if (test_bit(SID_ID_MAPPED, &psidid->state))
- memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+ cifs_copy_sid(ssid, &psidid->sid);
else
rc = -EINVAL;
}
@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *
static void copy_sec_desc(const struct cifs_ntsd *pntsd,
struct cifs_ntsd *pnntsd, __u32 sidsoffset)
{
- int i;
-
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
@@ -692,26 +697,14 @@ static void copy_sec_desc(const struct c
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset));
nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
-
- nowner_sid_ptr->revision = owner_sid_ptr->revision;
- nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
- for (i = 0; i < 6; i++)
- nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
- for (i = 0; i < 5; i++)
- nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
+ cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
/* copy group sid */
group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->gsidoffset));
ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
sizeof(struct cifs_sid));
-
- ngroup_sid_ptr->revision = group_sid_ptr->revision;
- ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
- for (i = 0; i < 6; i++)
- ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
- for (i = 0; i < 5; i++)
- ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
+ cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
return;
}
@@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_nt
kfree(nowner_sid_ptr);
return rc;
}
- memcpy(owner_sid_ptr, nowner_sid_ptr,
- sizeof(struct cifs_sid));
+ cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
kfree(nowner_sid_ptr);
*aclflag = CIFS_ACL_OWNER;
}
@@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_nt
kfree(ngroup_sid_ptr);
return rc;
}
- memcpy(group_sid_ptr, ngroup_sid_ptr,
- sizeof(struct cifs_sid));
+ cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
kfree(ngroup_sid_ptr);
*aclflag = CIFS_ACL_GROUP;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Colin Cross <[email protected]>
commit d38e0e3fed4f58bcddef4dc93a591dfe2f651cb0 upstream.
Commit 6bd4a5d96c08dc2380f8053b1bd4f879f55cd3c9 changed the
ANDROID_ALARM_GET_TIME ioctls from IOW to IOR. While technically
correct, the _IOC_DIR bits are ignored by alarm_ioctl, so the
commit breaks a userspace ABI used by all existing Android devices
for a purely cosmetic reason. Revert it.
Cc: Dae S. Kim <[email protected]>
Signed-off-by: Colin Cross <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/staging/android/android_alarm.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/drivers/staging/android/android_alarm.h
+++ b/drivers/staging/android/android_alarm.h
@@ -110,12 +110,10 @@ enum android_alarm_return_flags {
#define ANDROID_ALARM_WAIT _IO('a', 1)
#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size)
-
/* Set alarm */
#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec)
#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec)
#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec)
#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0)))
#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 00650931e52e97fe64096bec167f5a6780dfd94a)
Avoid dropping and retaking con->mutex in the ceph_con_send() case by
leaving locking up to the caller.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2441,12 +2441,10 @@ static void clear_standby(struct ceph_co
{
/* come back from STANDBY? */
if (test_and_clear_bit(STANDBY, &con->state)) {
- mutex_lock(&con->mutex);
dout("clear_standby %p and ++connect_seq\n", con);
con->connect_seq++;
WARN_ON(test_bit(WRITE_PENDING, &con->flags));
WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags));
- mutex_unlock(&con->mutex);
}
}
@@ -2483,11 +2481,12 @@ void ceph_con_send(struct ceph_connectio
le32_to_cpu(msg->hdr.front_len),
le32_to_cpu(msg->hdr.middle_len),
le32_to_cpu(msg->hdr.data_len));
+
+ clear_standby(con);
mutex_unlock(&con->mutex);
/* if there wasn't anything waiting to send before, queue
* new work */
- clear_standby(con);
if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
queue_con(con);
}
@@ -2574,7 +2573,9 @@ void ceph_msg_revoke_incoming(struct cep
void ceph_con_keepalive(struct ceph_connection *con)
{
dout("con_keepalive %p\n", con);
+ mutex_lock(&con->mutex);
clear_standby(con);
+ mutex_unlock(&con->mutex);
if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 &&
test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
queue_con(con);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit b9e06ef2e8706fe669b51f4364e3aeed58639eb2 upstream.
In reiserfs_quota_on() we do quite some work - for example unpacking
tail of a quota file. Thus we have to hold write lock until a moment
we call back into the quota code.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/reiserfs/super.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2170,8 +2170,11 @@ static int reiserfs_quota_on(struct supe
struct reiserfs_transaction_handle th;
int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
- if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
- return -EINVAL;
+ reiserfs_write_lock(sb);
+ if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+ err = -EINVAL;
+ goto out;
+ }
/* Quotafile not on the same filesystem? */
if (path->dentry->d_sb != sb) {
@@ -2213,8 +2216,10 @@ static int reiserfs_quota_on(struct supe
if (err)
goto out;
}
- err = dquot_quota_on(sb, type, format_id, path);
+ reiserfs_write_unlock(sb);
+ return dquot_quota_on(sb, type, format_id, path);
out:
+ reiserfs_write_unlock(sb);
return err;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Hocko <[email protected]>
commit 9a5a8f19b43430752067ecaee62fc59e11e88fa6 upstream.
oom_badness() takes a totalpages argument which says how many pages are
available and it uses it as a base for the score calculation. The value
is calculated by mem_cgroup_get_limit which considers both limit and
total_swap_pages (resp. memsw portion of it).
This is usually correct but since fe35004fbf9e ("mm: avoid swapping out
with swappiness==0") we do not swap when swappiness is 0 which means
that we cannot really use up all the totalpages pages. This in turn
confuses oom score calculation if the memcg limit is much smaller than
the available swap because the used memory (capped by the limit) is
negligible comparing to totalpages so the resulting score is too small
if adj!=0 (typically task with CAP_SYS_ADMIN or non zero oom_score_adj).
A wrong process might be selected as result.
The problem can be worked around by checking mem_cgroup_swappiness==0
and not considering swap at all in such a case.
Signed-off-by: Michal Hocko <[email protected]>
Acked-by: David Rientjes <[email protected]>
Acked-by: Johannes Weiner <[email protected]>
Acked-by: KOSAKI Motohiro <[email protected]>
Acked-by: KAMEZAWA Hiroyuki <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
Documentation/cgroups/memory.txt | 4 ++++
mm/memcontrol.c | 21 +++++++++++++++------
2 files changed, 19 insertions(+), 6 deletions(-)
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -466,6 +466,10 @@ Note:
5.3 swappiness
Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+Please note that unlike the global swappiness, memcg knob set to 0
+really prevents from any swapping even if there is a swap storage
+available. This might lead to memcg OOM killer if there are no file
+pages to reclaim.
Following cgroups' swappiness can't be changed.
- root cgroup (uses /proc/sys/vm/swappiness).
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1489,17 +1489,26 @@ static int mem_cgroup_count_children(str
u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
{
u64 limit;
- u64 memsw;
limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
- limit += total_swap_pages << PAGE_SHIFT;
- memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
/*
- * If memsw is finite and limits the amount of swap space available
- * to this memcg, return that limit.
+ * Do not consider swap space if we cannot swap due to swappiness
*/
- return min(limit, memsw);
+ if (mem_cgroup_swappiness(memcg)) {
+ u64 memsw;
+
+ limit += total_swap_pages << PAGE_SHIFT;
+ memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
+
+ /*
+ * If memsw is finite and limits the amount of swap space
+ * available to this memcg, return that limit.
+ */
+ limit = min(limit, memsw);
+ }
+
+ return limit;
}
static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg,
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 6bd9adbdf9ca6a052b0b7455ac67b925eb38cfad)
Usually, we are adding pg_temp entries or removing them. Occasionally they
update. In that case, osdmap_apply_incremental() was failing because the
rbtree entry already exists.
Fix by removing the existing entry before inserting a new one.
Fixes http://tracker.newdream.net/issues/2446
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osdmap.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -890,8 +890,12 @@ struct ceph_osdmap *osdmap_apply_increme
pglen = ceph_decode_32(p);
if (pglen) {
- /* insert */
ceph_decode_need(p, end, pglen*sizeof(u32), bad);
+
+ /* removing existing (if any) */
+ (void) __remove_pg_mapping(&map->pg_temp, pgid);
+
+ /* insert */
pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS);
if (!pg) {
err = -ENOMEM;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit ed96af646011412c2bf1ffe860db170db355fae5)
In prepare_connect_authorizer(), a connection's get_authorizer
method is called but ignores its return value. This function can
return an error, so check for it and return it if that ever occurs.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -658,6 +658,7 @@ static int prepare_connect_authorizer(st
void *auth_buf;
int auth_len;
int auth_protocol;
+ int ret;
if (!con->ops->get_authorizer) {
con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
@@ -673,11 +674,14 @@ static int prepare_connect_authorizer(st
auth_buf = NULL;
auth_len = 0;
auth_protocol = CEPH_AUTH_UNKNOWN;
- con->ops->get_authorizer(con, &auth_buf, &auth_len, &auth_protocol,
- &con->auth_reply_buf, &con->auth_reply_buf_len,
- con->auth_retry);
+ ret = con->ops->get_authorizer(con, &auth_buf, &auth_len,
+ &auth_protocol, &con->auth_reply_buf,
+ &con->auth_reply_buf_len, con->auth_retry);
mutex_lock(&con->mutex);
+ if (ret)
+ return ret;
+
if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
return -EAGAIN;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 739c905baa018c99003564ebc367d93aa44d4861)
Move the code that prepares to write the data portion of a message
into its own function.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -565,6 +565,24 @@ static void con_out_kvec_add(struct ceph
con->out_kvec_bytes += size;
}
+static void prepare_write_message_data(struct ceph_connection *con)
+{
+ struct ceph_msg *msg = con->out_msg;
+
+ BUG_ON(!msg);
+ BUG_ON(!msg->hdr.data_len);
+
+ /* initialize page iterator */
+ con->out_msg_pos.page = 0;
+ if (msg->pages)
+ con->out_msg_pos.page_pos = msg->page_alignment;
+ else
+ con->out_msg_pos.page_pos = 0;
+ con->out_msg_pos.data_pos = 0;
+ con->out_msg_pos.did_page_crc = false;
+ con->out_more = 1; /* data + footer will follow */
+}
+
/*
* Prepare footer for currently outgoing message, and finish things
* off. Assumes out_kvec* are already valid.. we just add on to the end.
@@ -657,26 +675,17 @@ static void prepare_write_message(struct
con->out_msg->footer.middle_crc = cpu_to_le32(crc);
} else
con->out_msg->footer.middle_crc = 0;
- con->out_msg->footer.data_crc = 0;
- dout("prepare_write_message front_crc %u data_crc %u\n",
+ dout("%s front_crc %u middle_crc %u\n", __func__,
le32_to_cpu(con->out_msg->footer.front_crc),
le32_to_cpu(con->out_msg->footer.middle_crc));
/* is there a data payload? */
- if (le32_to_cpu(m->hdr.data_len) > 0) {
- /* initialize page iterator */
- con->out_msg_pos.page = 0;
- if (m->pages)
- con->out_msg_pos.page_pos = m->page_alignment;
- else
- con->out_msg_pos.page_pos = 0;
- con->out_msg_pos.data_pos = 0;
- con->out_msg_pos.did_page_crc = false;
- con->out_more = 1; /* data + footer will follow */
- } else {
+ con->out_msg->footer.data_crc = 0;
+ if (m->hdr.data_len)
+ prepare_write_message_data(con);
+ else
/* no, queue up footer too and be done */
prepare_write_message_footer(con);
- }
set_bit(WRITE_PENDING, &con->flags);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xi Wang <[email protected]>
(cherry picked from commit ad3b904c07dfa88603689bf9a67bffbb9b99beb5)
`len' is read from network and thus needs validation. Otherwise a
large `len' would cause out-of-bounds access via the memcpy() call.
In addition, len = 0xffffffff would overflow the kmalloc() size,
leading to out-of-bounds write.
This patch adds a check of `len' via ceph_decode_need(). Also use
kstrndup rather than kmalloc/memcpy.
[[email protected]: added -ENOMEM return for null kstrndup() result]
Signed-off-by: Xi Wang <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osdmap.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -495,15 +495,16 @@ static int __decode_pool_names(void **p,
ceph_decode_32_safe(p, end, pool, bad);
ceph_decode_32_safe(p, end, len, bad);
dout(" pool %d len %d\n", pool, len);
+ ceph_decode_need(p, end, len, bad);
pi = __lookup_pg_pool(&map->pg_pools, pool);
if (pi) {
+ char *name = kstrndup(*p, len, GFP_NOFS);
+
+ if (!name)
+ return -ENOMEM;
kfree(pi->name);
- pi->name = kmalloc(len + 1, GFP_NOFS);
- if (pi->name) {
- memcpy(pi->name, *p, len);
- pi->name[len] = '\0';
- dout(" name is %s\n", pi->name);
- }
+ pi->name = name;
+ dout(" name is %s\n", pi->name);
}
*p += len;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 upstream.
When remounting reiserfs dquot_suspend() or dquot_resume() can be called.
These functions take dqonoff_mutex which ranks above write lock so we have
to drop it before calling into quota code.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/reiserfs/super.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1292,7 +1292,7 @@ static int reiserfs_remount(struct super
kfree(qf_names[i]);
#endif
err = -EINVAL;
- goto out_err;
+ goto out_unlock;
}
#ifdef CONFIG_QUOTA
handle_quota_files(s, qf_names, &qfmt);
@@ -1336,7 +1336,7 @@ static int reiserfs_remount(struct super
if (blocks) {
err = reiserfs_resize(s, blocks);
if (err != 0)
- goto out_err;
+ goto out_unlock;
}
if (*mount_flags & MS_RDONLY) {
@@ -1346,9 +1346,15 @@ static int reiserfs_remount(struct super
/* it is read-only already */
goto out_ok;
+ /*
+ * Drop write lock. Quota will retake it when needed and lock
+ * ordering requires calling dquot_suspend() without it.
+ */
+ reiserfs_write_unlock(s);
err = dquot_suspend(s, -1);
if (err < 0)
goto out_err;
+ reiserfs_write_lock(s);
/* try to remount file system with read-only permissions */
if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1358,7 +1364,7 @@ static int reiserfs_remount(struct super
err = journal_begin(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
/* Mounting a rw partition read-only. */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1373,7 +1379,7 @@ static int reiserfs_remount(struct super
if (reiserfs_is_journal_aborted(journal)) {
err = journal->j_errno;
- goto out_err;
+ goto out_unlock;
}
handle_data_mode(s, mount_options);
@@ -1382,7 +1388,7 @@ static int reiserfs_remount(struct super
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
err = journal_begin(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
/* Mount a partition which is read-only, read-write */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1399,11 +1405,17 @@ static int reiserfs_remount(struct super
SB_JOURNAL(s)->j_must_wait = 1;
err = journal_end(&th, s, 10);
if (err)
- goto out_err;
+ goto out_unlock;
s->s_dirt = 0;
if (!(*mount_flags & MS_RDONLY)) {
+ /*
+ * Drop write lock. Quota will retake it when needed and lock
+ * ordering requires calling dquot_resume() without it.
+ */
+ reiserfs_write_unlock(s);
dquot_resume(s, -1);
+ reiserfs_write_lock(s);
finish_unfinished(s);
reiserfs_xattr_init(s, *mount_flags);
}
@@ -1413,9 +1425,10 @@ out_ok:
reiserfs_write_unlock(s);
return 0;
+out_unlock:
+ reiserfs_write_unlock(s);
out_err:
kfree(new_opts);
- reiserfs_write_unlock(s);
return err;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sylvain Munaut <[email protected]>
(cherry picked from commit f0666b1ac875ff32fe290219b150ec62eebbe10e)
Avoid crashing if the crypto key payload was NULL, as when it was not correctly
allocated and initialized. Also, avoid leaking it.
Signed-off-by: Sylvain Munaut <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/crypto.c | 1 +
net/ceph/crypto.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) {
struct ceph_crypto_key *ckey = key->payload.data;
ceph_crypto_key_destroy(ckey);
+ kfree(ckey);
}
struct key_type key_type_ceph = {
--- a/net/ceph/crypto.h
+++ b/net/ceph/crypto.h
@@ -16,7 +16,8 @@ struct ceph_crypto_key {
static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
{
- kfree(key->key);
+ if (key)
+ kfree(key->key);
}
extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Artem Bityutskiy <[email protected]>
commit a28ad42a4a0c6f302f488f26488b8b37c9b30024 upstream.
This is a bugfix for a problem with the following symptoms:
1. A power cut happens
2. After reboot, we try to mount UBIFS
3. Mount fails with "No space left on device" error message
UBIFS complains like this:
UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB
The root cause of this problem is that when we mount, not all LEBs are
categorized. Only those which were read are. However, the
'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were
categorized and 'c->freeable_cnt' is valid, which is a false assumption.
This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()'
to always fall back to LPT scanning if no freeable LEBs were found.
This problem was reported by few people in the past, but Brent Taylor
was able to reproduce it and send me a flash image which cannot be mounted,
which made it easy to hunt the bug. Kudos to Brent.
Reported-by: Brent Taylor <[email protected]>
Signed-off-by: Artem Bityutskiy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ubifs/find.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
--- a/fs/ubifs/find.c
+++ b/fs/ubifs/find.c
@@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct u
if (!lprops) {
lprops = ubifs_fast_find_freeable(c);
if (!lprops) {
- ubifs_assert(c->freeable_cnt == 0);
- if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+ /*
+ * The first condition means the following: go scan the
+ * LPT if there are uncategorized lprops, which means
+ * there may be freeable LEBs there (UBIFS does not
+ * store the information about freeable LEBs in the
+ * master node).
+ */
+ if (c->in_a_category_cnt != c->main_lebs ||
+ c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+ ubifs_assert(c->freeable_cnt == 0);
lprops = scan_for_leb_for_idx(c);
if (IS_ERR(lprops)) {
err = PTR_ERR(lprops);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jones <[email protected]>
commit 88a693b5c1287be4da937699cb82068ce9db0135 upstream.
===============================
[ INFO: suspicious RCU usage. ]
3.5.0-rc1+ #63 Not tainted
-------------------------------
security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 1, debug_locks = 0
1 lock held by trinity-child1/8750:
#0: (sel_netnode_lock){+.....}, at: [<ffffffff812d8f8a>] sel_netnode_sid+0x16a/0x3e0
stack backtrace:
Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63
Call Trace:
[<ffffffff810cec2d>] lockdep_rcu_suspicious+0xfd/0x130
[<ffffffff812d91d1>] sel_netnode_sid+0x3b1/0x3e0
[<ffffffff812d8e20>] ? sel_netnode_find+0x1a0/0x1a0
[<ffffffff812d24a6>] selinux_socket_bind+0xf6/0x2c0
[<ffffffff810cd1dd>] ? trace_hardirqs_off+0xd/0x10
[<ffffffff810cdb55>] ? lock_release_holdtime.part.9+0x15/0x1a0
[<ffffffff81093841>] ? lock_hrtimer_base+0x31/0x60
[<ffffffff812c9536>] security_socket_bind+0x16/0x20
[<ffffffff815550ca>] sys_bind+0x7a/0x100
[<ffffffff816c03d5>] ? sysret_check+0x22/0x5d
[<ffffffff810d392d>] ? trace_hardirqs_on_caller+0x10d/0x1a0
[<ffffffff8133b09e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[<ffffffff816c03a9>] system_call_fastpath+0x16/0x1b
This patch below does what Paul McKenney suggested in the previous thread.
Signed-off-by: Dave Jones <[email protected]>
Reviewed-by: Paul E. McKenney <[email protected]>
Acked-by: Paul Moore <[email protected]>
Cc: Eric Paris <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: James Morris <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
security/selinux/netnode.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct se
if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
struct sel_netnode *tail;
tail = list_entry(
- rcu_dereference(sel_netnode_hash[idx].list.prev),
+ rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+ lockdep_is_held(&sel_netnode_lock)),
struct sel_netnode, list);
list_del_rcu(&tail->list);
kfree_rcu(tail, rcu);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit b7a9e5dd40f17a48a72f249b8bbc989b63bae5fd)
The peer name may change on each open attempt, even when the connection is
reused.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 7 ++++---
include/linux/ceph/messenger.h | 4 ++--
net/ceph/messenger.c | 12 +++++++-----
net/ceph/mon_client.c | 4 ++--
net/ceph/osd_client.c | 10 ++++++----
5 files changed, 21 insertions(+), 16 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -394,8 +394,7 @@ static struct ceph_mds_session *register
s->s_seq = 0;
mutex_init(&s->s_mutex);
- ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr,
- CEPH_ENTITY_TYPE_MDS, mds);
+ ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr);
spin_lock_init(&s->s_gen_ttl_lock);
s->s_cap_gen = 0;
@@ -437,7 +436,8 @@ static struct ceph_mds_session *register
mdsc->sessions[mds] = s;
atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */
- ceph_con_open(&s->s_con, ceph_mdsmap_get_addr(mdsc->mdsmap, mds));
+ ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds,
+ ceph_mdsmap_get_addr(mdsc->mdsmap, mds));
return s;
@@ -2529,6 +2529,7 @@ static void send_mds_reconnect(struct ce
session->s_seq = 0;
ceph_con_open(&session->s_con,
+ CEPH_ENTITY_TYPE_MDS, mds,
ceph_mdsmap_get_addr(mdsc->mdsmap, mds));
/* replay unsafe requests */
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -224,9 +224,9 @@ extern void ceph_messenger_init(struct c
extern void ceph_con_init(struct ceph_connection *con, void *private,
const struct ceph_connection_operations *ops,
- struct ceph_messenger *msgr, __u8 entity_type,
- __u64 entity_num);
+ struct ceph_messenger *msgr);
extern void ceph_con_open(struct ceph_connection *con,
+ __u8 entity_type, __u64 entity_num,
struct ceph_entity_addr *addr);
extern bool ceph_con_opened(struct ceph_connection *con);
extern void ceph_con_close(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -523,12 +523,17 @@ EXPORT_SYMBOL(ceph_con_close);
/*
* Reopen a closed connection, with a new peer address.
*/
-void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr)
+void ceph_con_open(struct ceph_connection *con,
+ __u8 entity_type, __u64 entity_num,
+ struct ceph_entity_addr *addr)
{
dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
set_bit(OPENING, &con->state);
WARN_ON(!test_and_clear_bit(CLOSED, &con->state));
+ con->peer_name.type = (__u8) entity_type;
+ con->peer_name.num = cpu_to_le64(entity_num);
+
memcpy(&con->peer_addr, addr, sizeof(*addr));
con->delay = 0; /* reset backoff memory */
queue_con(con);
@@ -548,7 +553,7 @@ bool ceph_con_opened(struct ceph_connect
*/
void ceph_con_init(struct ceph_connection *con, void *private,
const struct ceph_connection_operations *ops,
- struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num)
+ struct ceph_messenger *msgr)
{
dout("con_init %p\n", con);
memset(con, 0, sizeof(*con));
@@ -558,9 +563,6 @@ void ceph_con_init(struct ceph_connectio
con_sock_state_init(con);
- con->peer_name.type = (__u8) entity_type;
- con->peer_name.num = cpu_to_le64(entity_num);
-
mutex_init(&con->mutex);
INIT_LIST_HEAD(&con->out_queue);
INIT_LIST_HEAD(&con->out_sent);
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -143,11 +143,11 @@ static int __open_session(struct ceph_mo
monc->want_next_osdmap = !!monc->want_next_osdmap;
ceph_con_init(&monc->con, monc, &mon_con_ops,
- &monc->client->msgr,
- CEPH_ENTITY_TYPE_MON, monc->cur_mon);
+ &monc->client->msgr);
dout("open_session mon%d opening\n", monc->cur_mon);
ceph_con_open(&monc->con,
+ CEPH_ENTITY_TYPE_MON, monc->cur_mon,
&monc->monmap->mon_inst[monc->cur_mon].addr);
/* initiatiate authentication handshake */
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -639,8 +639,7 @@ static struct ceph_osd *create_osd(struc
INIT_LIST_HEAD(&osd->o_osd_lru);
osd->o_incarnation = 1;
- ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr,
- CEPH_ENTITY_TYPE_OSD, onum);
+ ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr);
INIT_LIST_HEAD(&osd->o_keepalive_item);
return osd;
@@ -750,7 +749,8 @@ static int __reset_osd(struct ceph_osd_c
ret = -EAGAIN;
} else {
ceph_con_close(&osd->o_con);
- ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]);
+ ceph_con_open(&osd->o_con, CEPH_ENTITY_TYPE_OSD, osd->o_osd,
+ &osdc->osdmap->osd_addr[osd->o_osd]);
osd->o_incarnation++;
}
return ret;
@@ -1005,7 +1005,9 @@ static int __map_request(struct ceph_osd
dout("map_request osd %p is osd%d\n", req->r_osd, o);
__insert_osd(osdc, req->r_osd);
- ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]);
+ ceph_con_open(&req->r_osd->o_con,
+ CEPH_ENTITY_TYPE_OSD, o,
+ &osdc->osdmap->osd_addr[o]);
}
if (req->r_osd) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arik Nemtsov <[email protected]>
commit 987c285c2ae2e4e32aca3a9b3252d28171c75711 upstream.
These are accessed without a lock when ending STA PSM. If the
sta_cleanup timer accesses these lists at the same time, we might crash.
This may fix some mysterious crashes we had during
ieee80211_sta_ps_deliver_wakeup.
Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Ido Yariv <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/mac80211/sta_info.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -959,6 +959,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
struct ieee80211_local *local = sdata->local;
struct sk_buff_head pending;
int filtered = 0, buffered = 0, ac;
+ unsigned long flags;
clear_sta_flag(sta, WLAN_STA_SP);
@@ -974,12 +975,16 @@ void ieee80211_sta_ps_deliver_wakeup(str
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
int count = skb_queue_len(&pending), tmp;
+ spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending);
+ spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
tmp = skb_queue_len(&pending);
filtered += tmp - count;
count = tmp;
+ spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
+ spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
tmp = skb_queue_len(&pending);
buffered += tmp - count;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Yakui <[email protected]>
commit ac207ed2471150e06af0afc76e4becc701fa2733 upstream.
The TTM page can be allocated from high memory. In such case it is
wrong to use the page_address(page) as the virtual address for the high memory
page.
bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=50241
Signed-off-by: Zhao Yakui <[email protected]>
Reviewed-by: Thomas Hellstrom <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **p
/* clear the pages coming from the pool if requested */
if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
list_for_each_entry(p, &plist, lru) {
- clear_page(page_address(p));
+ if (PageHighMem(p))
+ clear_highpage(p);
+ else
+ clear_page(page_address(p));
}
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tyler Hicks <[email protected]>
commit 069ddcda37b2cf5bb4b6031a944c0e9359213262 upstream.
When the eCryptfs mount options do not include '-o acl', but the lower
filesystem's mount options do include 'acl', the MS_POSIXACL flag is not
flipped on in the eCryptfs super block flags. This flag is what the VFS
checks in do_last() when deciding if the current umask should be applied
to a newly created inode's mode or not. When a default POSIX ACL mask is
set on a directory, the current umask is incorrectly applied to new
inodes created in the directory. This patch ignores the MS_POSIXACL flag
passed into ecryptfs_mount() and sets the flag on the eCryptfs super
block depending on the flag's presence on the lower super block.
Additionally, it is incorrect to allow a writeable eCryptfs mount on top
of a read-only lower mount. This missing check did not allow writes to
the read-only lower mount because permissions checks are still performed
on the lower filesystem's objects but it is best to simply not allow a
rw mount on top of ro mount. However, a ro eCryptfs mount on top of a rw
mount is valid and still allowed.
https://launchpad.net/bugs/1009207
Signed-off-by: Tyler Hicks <[email protected]>
Reported-by: Stefan Beller <[email protected]>
Cc: John Johansen <[email protected]>
Cc: Herton Ronaldo Krzesinski <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/main.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -506,7 +506,6 @@ static struct dentry *ecryptfs_mount(str
goto out;
}
- s->s_flags = flags;
rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY);
if (rc)
goto out1;
@@ -542,6 +541,15 @@ static struct dentry *ecryptfs_mount(str
}
ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
+
+ /**
+ * Set the POSIX ACL flag based on whether they're enabled in the lower
+ * mount. Force a read-only eCryptfs mount if the lower mount is ro.
+ * Allow a ro eCryptfs mount even when the lower mount is rw.
+ */
+ s->s_flags = flags & ~MS_POSIXACL;
+ s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL);
+
s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
s->s_blocksize = path.dentry->d_sb->s_blocksize;
s->s_magic = ECRYPTFS_SUPER_MAGIC;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Paris <[email protected]>
commit 848561d368751a1c0f679b9f045a02944506a801 upstream.
Anders Blomdell noted in 2010 that Fanotify lost events and provided a
test case. Eric Paris confirmed it was a bug and posted a fix to the
list
https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE
but never applied it. Repeated attempts over time to actually get him
to apply it have never had a reply from anyone who has raised it
So apply it anyway
Signed-off-by: Alan Cox <[email protected]>
Reported-by: Anders Blomdell <[email protected]>
Cc: Eric Paris <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/notify/fanotify/fanotify.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify
if ((old->path.mnt == new->path.mnt) &&
(old->path.dentry == new->path.dentry))
return true;
+ break;
case (FSNOTIFY_EVENT_NONE):
return true;
default:
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Frederic Sowa <[email protected]>
[ Upstream commit d4596bad2a713fcd0def492b1960e6d899d5baa8 ]
Cc: Stephen Hemminger <[email protected]>
Signed-off-by: Hannes Frederic Sowa <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ipv6/ipv6_sockglue.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -828,6 +828,7 @@ pref_skip_coa:
if (val < 0 || val > 255)
goto e_inval;
np->min_hopcount = val;
+ retv = 0;
break;
case IPV6_DONTFRAG:
np->dontfrag = valbool;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 188048bce311ee41e5178bc3255415d0eae28423)
Currently the socket state change event handler records an error
message on a connection to distinguish a close while connecting from
a close while a connection was already established.
Changing connection information during handling of a socket event is
not very clean, so instead move this assignment inside con_work(),
where it can be done during normal connection-level processing (and
under protection of the connection mutex as well).
Move the handling of a socket closed event up to the top of the
processing loop in con_work(); there's no point in handling backoff
etc. if we have a newly-closed socket to take care of.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -261,13 +261,8 @@ static void ceph_sock_state_change(struc
case TCP_CLOSE_WAIT:
dout("%s TCP_CLOSE_WAIT\n", __func__);
con_sock_state_closing(con);
- if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) {
- if (test_bit(CONNECTING, &con->state))
- con->error_msg = "connection failed";
- else
- con->error_msg = "socket closed";
+ if (!test_and_set_bit(SOCK_CLOSED, &con->flags))
queue_con(con);
- }
break;
case TCP_ESTABLISHED:
dout("%s TCP_ESTABLISHED\n", __func__);
@@ -2187,6 +2182,14 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
+ if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
+ if (test_bit(CONNECTING, &con->state))
+ con->error_msg = "connection failed";
+ else
+ con->error_msg = "socket closed";
+ goto fault;
+ }
+
if (test_and_clear_bit(BACKOFF, &con->flags)) {
dout("con_work %p backing off\n", con);
if (queue_delayed_work(ceph_msgr_wq, &con->work,
@@ -2216,9 +2219,6 @@ restart:
con_close_socket(con);
}
- if (test_and_clear_bit(SOCK_CLOSED, &con->flags))
- goto fault;
-
ret = try_read(con);
if (ret == -EAGAIN)
goto restart;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit ef4da45828603df57e5e21b8aa21a66ce309f79b upstream.
VT1802 codec provides the invalid connection lists of NID 0x24 and
0x33 containing the routes to a non-exist widget 0x3e. This confuses
the auto-parser. Fix it up in the driver by overriding these
connections.
Reported-by: Massimo Del Fedele <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_via.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -3665,6 +3665,18 @@ static void set_widgets_power_state_vt20
update_power_state(codec, 0x21, AC_PWRST_D3);
}
+/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
+ * Replace this with mixer NID 0x1c
+ */
+static void fix_vt1802_connections(struct hda_codec *codec)
+{
+ static hda_nid_t conn_24[] = { 0x14, 0x1c };
+ static hda_nid_t conn_33[] = { 0x1c };
+
+ snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
+ snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
+}
+
/* patch for vt2002P */
static int patch_vt2002P(struct hda_codec *codec)
{
@@ -3679,6 +3691,8 @@ static int patch_vt2002P(struct hda_code
spec->aa_mix_nid = 0x21;
override_mic_boost(codec, 0x2b, 0, 3, 40);
override_mic_boost(codec, 0x29, 0, 3, 40);
+ if (spec->codec_type == VT1802)
+ fix_vt1802_connections(codec);
add_secret_dac_path(codec);
/* automatic parse from the BIOS config */
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Sally <[email protected]>
commit 5f5b331d5c21228a6519dcb793fc1629646c51a6 upstream.
The issue occurs when eCryptfs is mounted with a cipher supported by
the crypto subsystem but not by eCryptfs. The mount succeeds and an
error does not occur until a write. This change checks for eCryptfs
cipher support at mount time.
Resolves Launchpad issue #338914, reported by Tyler Hicks in 03/2009.
https://bugs.launchpad.net/ecryptfs/+bug/338914
Signed-off-by: Tim Sally <[email protected]>
Signed-off-by: Tyler Hicks <[email protected]>
Cc: Herton Ronaldo Krzesinski <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ecryptfs/main.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -280,6 +280,7 @@ static int ecryptfs_parse_options(struct
char *fnek_src;
char *cipher_key_bytes_src;
char *fn_cipher_key_bytes_src;
+ u8 cipher_code;
*check_ruid = 0;
@@ -421,6 +422,18 @@ static int ecryptfs_parse_options(struct
&& !fn_cipher_key_bytes_set)
mount_crypt_stat->global_default_fn_cipher_key_bytes =
mount_crypt_stat->global_default_cipher_key_size;
+
+ cipher_code = ecryptfs_code_for_cipher_string(
+ mount_crypt_stat->global_default_cipher_name,
+ mount_crypt_stat->global_default_cipher_key_size);
+ if (!cipher_code) {
+ ecryptfs_printk(KERN_ERR,
+ "eCryptfs doesn't support cipher: %s",
+ mount_crypt_stat->global_default_cipher_name);
+ rc = -EINVAL;
+ goto out;
+ }
+
mutex_lock(&key_tfm_list_mutex);
if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
NULL)) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 35f9f8a09e1e88e31bd34a1e645ca0e5f070dd5c)
There is a race between two __unregister_request() callers: the
reply path and the ceph_osdc_wait_request(). If we get a reply
*and* the timeout expires at roughly the same time, both callers
will try to unregister the request, and the second one will do bad
things.
Simply check if the request is still already unregistered; if so,
return immediately and do nothing.
Fixes http://tracker.newdream.net/issues/2420
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osd_client.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -841,6 +841,12 @@ static void register_request(struct ceph
static void __unregister_request(struct ceph_osd_client *osdc,
struct ceph_osd_request *req)
{
+ if (RB_EMPTY_NODE(&req->r_node)) {
+ dout("__unregister_request %p tid %lld not registered\n",
+ req, req->r_tid);
+ return;
+ }
+
dout("__unregister_request %p tid %lld\n", req, req->r_tid);
rb_erase(&req->r_node, &osdc->requests);
osdc->num_requests--;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Walp <[email protected]>
commit 0481776b7a70f09acf7d9d97c288c3a8403fbfe4 upstream.
RTL_GIGA_MAC_VER_35 includes no multicast hardware filter.
Signed-off-by: Nathan Walp <[email protected]>
Suggested-by: Hayes Wang <[email protected]>
Acked-by: Francois Romieu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/net/ethernet/realtek/r8169.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -4131,6 +4131,9 @@ static void rtl_set_rx_mode(struct net_d
mc_filter[1] = swab32(data);
}
+ if (tp->mac_version == RTL_GIGA_MAC_VER_35)
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+
RTL_W32(MAR0 + 4, mc_filter[1]);
RTL_W32(MAR0 + 0, mc_filter[0]);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit a59b55a602b6c741052d79c1e3643f8440cddd27)
Take the con mutex before checking whether the connection is closed to
avoid racing with someone else closing it.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2453,22 +2453,20 @@ static void clear_standby(struct ceph_co
*/
void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
{
- if (test_bit(CLOSED, &con->state)) {
- dout("con_send %p closed, dropping %p\n", con, msg);
- ceph_msg_put(msg);
- return;
- }
-
/* set src+dst */
msg->hdr.src = con->msgr->inst.name;
-
BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len));
-
msg->needs_out_seq = true;
- /* queue */
mutex_lock(&con->mutex);
+ if (test_bit(CLOSED, &con->state)) {
+ dout("con_send %p closed, dropping %p\n", con, msg);
+ ceph_msg_put(msg);
+ mutex_unlock(&con->mutex);
+ return;
+ }
+
BUG_ON(msg->con != NULL);
msg->con = con->ops->get(con);
BUG_ON(msg->con == NULL);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Millbrandt <[email protected]>
commit 55c6f4cb6ef49afbb86222c6a3ff85329199c729 upstream.
When MCLK is supplied externally and BCLK and LRC are configured as outputs
(codec is master), the PLL values are only calculated correctly on the first
transmission. On subsequent transmissions, at differenct sample rates, the
wrong PLL values are used. Test for f_opclk instead of f_pllout to determine
if the PLL values are needed.
Signed-off-by: Eric Millbrandt <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/soc/codecs/wm8978.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -783,7 +783,7 @@ static int wm8978_hw_params(struct snd_p
wm8978->mclk_idx = -1;
f_sel = wm8978->f_mclk;
} else {
- if (!wm8978->f_pllout) {
+ if (!wm8978->f_opclk) {
/* We only enter here, if OPCLK is not used */
int ret = wm8978_configure_pll(codec);
if (ret < 0)
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kailang Yang <[email protected]>
commit 19a62823eae453619604636082085812c14ee391 upstream.
Signed-off-by: Kailang Yang <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_realtek.c | 2 ++
1 file changed, 2 insertions(+)
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7047,6 +7047,7 @@ static const struct hda_codec_preset snd
.patch = patch_alc662 },
{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
+ { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
@@ -7064,6 +7065,7 @@ static const struct hda_codec_preset snd
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
{ .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
{ .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
+ { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
{} /* terminator */
};
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mojiong Qiu <[email protected]>
commit 772aebcefeff310f80e32b874988af0076cb799d upstream.
exit_idle() should be called after irq_enter(), otherwise it throws:
[ INFO: suspicious RCU usage. ]
3.6.5 #1 Not tainted
-------------------------------
include/linux/rcupdate.h:725 rcu_read_lock() used illegally while idle!
other info that might help us debug this:
RCU used illegally from idle CPU!
rcu_scheduler_active = 1, debug_locks = 1
RCU used illegally from extended quiescent state!
1 lock held by swapper/0/0:
#0: (rcu_read_lock){......}, at: [<ffffffff810e9fe0>] __atomic_notifier_call_chain+0x0/0x140
stack backtrace:
Pid: 0, comm: swapper/0 Not tainted 3.6.5 #1
Call Trace:
<IRQ> [<ffffffff811259a2>] lockdep_rcu_suspicious+0xe2/0x130
[<ffffffff810ea10c>] __atomic_notifier_call_chain+0x12c/0x140
[<ffffffff810e9fe0>] ? atomic_notifier_chain_unregister+0x90/0x90
[<ffffffff811216cd>] ? trace_hardirqs_off+0xd/0x10
[<ffffffff810ea136>] atomic_notifier_call_chain+0x16/0x20
[<ffffffff810777c3>] exit_idle+0x43/0x50
[<ffffffff81568865>] xen_evtchn_do_upcall+0x25/0x50
[<ffffffff81aa690e>] xen_do_hypervisor_callback+0x1e/0x30
<EOI> [<ffffffff810013aa>] ? hypercall_page+0x3aa/0x1000
[<ffffffff810013aa>] ? hypercall_page+0x3aa/0x1000
[<ffffffff81061540>] ? xen_safe_halt+0x10/0x20
[<ffffffff81075cfa>] ? default_idle+0xba/0x570
[<ffffffff810778af>] ? cpu_idle+0xdf/0x140
[<ffffffff81a4d881>] ? rest_init+0x135/0x144
[<ffffffff81a4d74c>] ? csum_partial_copy_generic+0x16c/0x16c
[<ffffffff82520c45>] ? start_kernel+0x3db/0x3e8
[<ffffffff8252066a>] ? repair_env_string+0x5a/0x5a
[<ffffffff82520356>] ? x86_64_start_reservations+0x131/0x135
[<ffffffff82524aca>] ? xen_start_kernel+0x465/0x46
Git commit 98ad1cc14a5c4fd658f9d72c6ba5c86dfd3ce0d5
Author: Frederic Weisbecker <[email protected]>
Date: Fri Oct 7 18:22:09 2011 +0200
x86: Call idle notifier after irq_enter()
did this, but it missed the Xen code.
Signed-off-by: Mojiong Qiu <[email protected]>
Signed-off-by: Konrad Rzeszutek Wilk <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/xen/events.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -1365,8 +1365,8 @@ void xen_evtchn_do_upcall(struct pt_regs
{
struct pt_regs *old_regs = set_irq_regs(regs);
- exit_idle();
irq_enter();
+ exit_idle();
__xen_evtchn_do_upcall();
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 5821bd8ccdf5d17ab2c391c773756538603838c3)
This patch gathers a few small changes in "net/ceph/messenger.c":
out_msg_pos_next()
- small logic change that mostly affects indentation
write_partial_msg_pages().
- use a local variable trail_off to represent the offset into
a message of the trail portion of the data (if present)
- once we are in the trail portion we will always be there, so we
don't always need to check against our data position
- avoid computing len twice after we've reached the trail
- get rid of the variable tmpcrc, which is not needed
- trail_off and trail_len never change so mark them const
- update some comments
read_partial_message_bio()
- bio_iovec_idx() will never return an error, so don't bother
checking for it
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 63 +++++++++++++++++++++++++--------------------------
1 file changed, 31 insertions(+), 32 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -907,21 +907,23 @@ static void out_msg_pos_next(struct ceph
con->out_msg_pos.data_pos += sent;
con->out_msg_pos.page_pos += sent;
- if (sent == len) {
- con->out_msg_pos.page_pos = 0;
- con->out_msg_pos.page++;
- con->out_msg_pos.did_page_crc = false;
- if (in_trail)
- list_move_tail(&page->lru,
- &msg->trail->head);
- else if (msg->pagelist)
- list_move_tail(&page->lru,
- &msg->pagelist->head);
+ if (sent < len)
+ return;
+
+ BUG_ON(sent != len);
+ con->out_msg_pos.page_pos = 0;
+ con->out_msg_pos.page++;
+ con->out_msg_pos.did_page_crc = false;
+ if (in_trail)
+ list_move_tail(&page->lru,
+ &msg->trail->head);
+ else if (msg->pagelist)
+ list_move_tail(&page->lru,
+ &msg->pagelist->head);
#ifdef CONFIG_BLOCK
- else if (msg->bio)
- iter_bio_next(&msg->bio_iter, &msg->bio_seg);
+ else if (msg->bio)
+ iter_bio_next(&msg->bio_iter, &msg->bio_seg);
#endif
- }
}
/*
@@ -940,30 +942,31 @@ static int write_partial_msg_pages(struc
int ret;
int total_max_write;
bool in_trail = false;
- size_t trail_len = (msg->trail ? msg->trail->length : 0);
+ const size_t trail_len = (msg->trail ? msg->trail->length : 0);
+ const size_t trail_off = data_len - trail_len;
dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n",
con, msg, con->out_msg_pos.page, msg->nr_pages,
con->out_msg_pos.page_pos);
+ /*
+ * Iterate through each page that contains data to be
+ * written, and send as much as possible for each.
+ *
+ * If we are calculating the data crc (the default), we will
+ * need to map the page. If we have no pages, they have
+ * been revoked, so use the zero page.
+ */
while (data_len > con->out_msg_pos.data_pos) {
struct page *page = NULL;
int max_write = PAGE_SIZE;
int bio_offset = 0;
- total_max_write = data_len - trail_len -
- con->out_msg_pos.data_pos;
-
- /*
- * if we are calculating the data crc (the default), we need
- * to map the page. if our pages[] has been revoked, use the
- * zero page.
- */
-
- /* have we reached the trail part of the data? */
- if (con->out_msg_pos.data_pos >= data_len - trail_len) {
- in_trail = true;
+ in_trail = in_trail || con->out_msg_pos.data_pos >= trail_off;
+ if (!in_trail)
+ total_max_write = trail_off - con->out_msg_pos.data_pos;
+ if (in_trail) {
total_max_write = data_len - con->out_msg_pos.data_pos;
page = list_first_entry(&msg->trail->head,
@@ -990,14 +993,13 @@ static int write_partial_msg_pages(struc
if (do_datacrc && !con->out_msg_pos.did_page_crc) {
void *base;
- u32 crc;
- u32 tmpcrc = le32_to_cpu(msg->footer.data_crc);
+ u32 crc = le32_to_cpu(msg->footer.data_crc);
char *kaddr;
kaddr = kmap(page);
BUG_ON(kaddr == NULL);
base = kaddr + con->out_msg_pos.page_pos + bio_offset;
- crc = crc32c(tmpcrc, base, len);
+ crc = crc32c(crc, base, len);
msg->footer.data_crc = cpu_to_le32(crc);
con->out_msg_pos.did_page_crc = true;
}
@@ -1702,9 +1704,6 @@ static int read_partial_message_bio(stru
void *p;
int ret, left;
- if (IS_ERR(bv))
- return PTR_ERR(bv);
-
left = min((int)(data_len - con->in_msg_pos.data_pos),
(int)(bv->bv_len - con->in_msg_pos.page_pos));
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Schwab <[email protected]>
commit 34fa78b59c52d1db3513db4c1a999db26b2e9ac2 upstream.
The sigaddset/sigdelset/sigismember functions that are implemented with
bitfield insn cannot allow the sigset argument to be placed in a data
register since the sigset is wider than 32 bits. Remove the "d"
constraint from the asm statements.
The effect of the bug is that sending RT signals does not work, the signal
number is truncated modulo 32.
Signed-off-by: Andreas Schwab <[email protected]>
Signed-off-by: Geert Uytterhoeven <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/m68k/include/asm/signal.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/m68k/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal.h
@@ -156,7 +156,7 @@ typedef struct sigaltstack {
static inline void sigaddset(sigset_t *set, int _sig)
{
asm ("bfset %0{%1,#1}"
- : "+od" (*set)
+ : "+o" (*set)
: "id" ((_sig - 1) ^ 31)
: "cc");
}
@@ -164,7 +164,7 @@ static inline void sigaddset(sigset_t *s
static inline void sigdelset(sigset_t *set, int _sig)
{
asm ("bfclr %0{%1,#1}"
- : "+od" (*set)
+ : "+o" (*set)
: "id" ((_sig - 1) ^ 31)
: "cc");
}
@@ -180,7 +180,7 @@ static inline int __gen_sigismember(sigs
int ret;
asm ("bfextu %1{%2,#1},%0"
: "=d" (ret)
- : "od" (*set), "id" ((_sig-1) ^ 31)
+ : "o" (*set), "id" ((_sig-1) ^ 31)
: "cc");
return ret;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 4a8616920860920abaa51193146fe36b38ef09aa)
Rename flags with CON_FLAG prefix, move the definitions into the c file,
and (better) document their meaning.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 10 ------
net/ceph/messenger.c | 62 +++++++++++++++++++++++------------------
2 files changed, 36 insertions(+), 36 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -107,16 +107,6 @@ struct ceph_msg_pos {
#define MAX_DELAY_INTERVAL (5 * 60 * HZ)
/*
- * ceph_connection flag bits
- */
-
-#define LOSSYTX 0 /* we can close channel or drop messages on errors */
-#define KEEPALIVE_PENDING 3
-#define WRITE_PENDING 4 /* we have data ready to send */
-#define SOCK_CLOSED 11 /* socket state changed to closed */
-#define BACKOFF 15
-
-/*
* A single connection with another host.
*
* We maintain a queue of outgoing messages, and some session state to
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -87,6 +87,15 @@
#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */
#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */
+/*
+ * ceph_connection flag bits
+ */
+#define CON_FLAG_LOSSYTX 0 /* we can close channel or drop
+ * messages on errors */
+#define CON_FLAG_KEEPALIVE_PENDING 1 /* we need to send a keepalive */
+#define CON_FLAG_WRITE_PENDING 2 /* we have data ready to send */
+#define CON_FLAG_SOCK_CLOSED 3 /* socket state changed to closed */
+#define CON_FLAG_BACKOFF 4 /* need to retry queuing delayed work */
/* static tag bytes (protocol control messages) */
static char tag_msg = CEPH_MSGR_TAG_MSG;
@@ -288,7 +297,7 @@ static void ceph_sock_write_space(struct
* buffer. See net/ipv4/tcp_input.c:tcp_check_space()
* and net/core/stream.c:sk_stream_write_space().
*/
- if (test_bit(WRITE_PENDING, &con->flags)) {
+ if (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) {
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
dout("%s %p queueing write work\n", __func__, con);
clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
@@ -313,7 +322,7 @@ static void ceph_sock_state_change(struc
case TCP_CLOSE_WAIT:
dout("%s TCP_CLOSE_WAIT\n", __func__);
con_sock_state_closing(con);
- set_bit(SOCK_CLOSED, &con->flags);
+ set_bit(CON_FLAG_SOCK_CLOSED, &con->flags);
queue_con(con);
break;
case TCP_ESTABLISHED:
@@ -449,12 +458,12 @@ static int con_close_socket(struct ceph_
con->sock = NULL;
/*
- * Forcibly clear the SOCK_CLOSE flag. It gets set
+ * Forcibly clear the SOCK_CLOSED flag. It gets set
* independent of the connection mutex, and we could have
* received a socket close event before we had the chance to
* shut the socket down.
*/
- clear_bit(SOCK_CLOSED, &con->flags);
+ clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags);
con_sock_state_closed(con);
return rc;
}
@@ -516,9 +525,9 @@ void ceph_con_close(struct ceph_connecti
ceph_pr_addr(&con->peer_addr.in_addr));
con->state = CON_STATE_CLOSED;
- clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */
- clear_bit(KEEPALIVE_PENDING, &con->flags);
- clear_bit(WRITE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */
+ clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
reset_connection(con);
con->peer_global_seq = 0;
@@ -770,7 +779,7 @@ static void prepare_write_message(struct
/* no, queue up footer too and be done */
prepare_write_message_footer(con);
- set_bit(WRITE_PENDING, &con->flags);
+ set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
}
/*
@@ -791,7 +800,7 @@ static void prepare_write_ack(struct cep
&con->out_temp_ack);
con->out_more = 1; /* more will follow.. eventually.. */
- set_bit(WRITE_PENDING, &con->flags);
+ set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
}
/*
@@ -802,7 +811,7 @@ static void prepare_write_keepalive(stru
dout("prepare_write_keepalive %p\n", con);
con_out_kvec_reset(con);
con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive);
- set_bit(WRITE_PENDING, &con->flags);
+ set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
}
/*
@@ -845,7 +854,7 @@ static void prepare_write_banner(struct
&con->msgr->my_enc_addr);
con->out_more = 0;
- set_bit(WRITE_PENDING, &con->flags);
+ set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
}
static int prepare_write_connect(struct ceph_connection *con)
@@ -896,7 +905,7 @@ static int prepare_write_connect(struct
auth->authorizer_buf);
con->out_more = 0;
- set_bit(WRITE_PENDING, &con->flags);
+ set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
return 0;
}
@@ -1622,7 +1631,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_reply.connect_seq));
if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
- set_bit(LOSSYTX, &con->flags);
+ set_bit(CON_FLAG_LOSSYTX, &con->flags);
con->delay = 0; /* reset backoff memory */
@@ -2061,14 +2070,15 @@ do_next:
prepare_write_ack(con);
goto more;
}
- if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) {
+ if (test_and_clear_bit(CON_FLAG_KEEPALIVE_PENDING,
+ &con->flags)) {
prepare_write_keepalive(con);
goto more;
}
}
/* Nothing to do! */
- clear_bit(WRITE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
dout("try_write nothing else to write.\n");
ret = 0;
out:
@@ -2241,7 +2251,7 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
- if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
+ if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) {
switch (con->state) {
case CON_STATE_CONNECTING:
con->error_msg = "connection failed";
@@ -2260,7 +2270,7 @@ restart:
goto fault;
}
- if (test_and_clear_bit(BACKOFF, &con->flags)) {
+ if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) {
dout("con_work %p backing off\n", con);
if (queue_delayed_work(ceph_msgr_wq, &con->work,
round_jiffies_relative(con->delay))) {
@@ -2336,7 +2346,7 @@ static void ceph_fault(struct ceph_conne
con_close_socket(con);
- if (test_bit(LOSSYTX, &con->flags)) {
+ if (test_bit(CON_FLAG_LOSSYTX, &con->flags)) {
dout("fault on LOSSYTX channel, marking CLOSED\n");
con->state = CON_STATE_CLOSED;
goto out_unlock;
@@ -2356,9 +2366,9 @@ static void ceph_fault(struct ceph_conne
/* If there are no messages queued or keepalive pending, place
* the connection in a STANDBY state */
if (list_empty(&con->out_queue) &&
- !test_bit(KEEPALIVE_PENDING, &con->flags)) {
+ !test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) {
dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con);
- clear_bit(WRITE_PENDING, &con->flags);
+ clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
con->state = CON_STATE_STANDBY;
} else {
/* retry after a delay. */
@@ -2383,7 +2393,7 @@ static void ceph_fault(struct ceph_conne
* that when con_work restarts we schedule the
* delay then.
*/
- set_bit(BACKOFF, &con->flags);
+ set_bit(CON_FLAG_BACKOFF, &con->flags);
}
}
@@ -2440,8 +2450,8 @@ static void clear_standby(struct ceph_co
dout("clear_standby %p and ++connect_seq\n", con);
con->state = CON_STATE_PREOPEN;
con->connect_seq++;
- WARN_ON(test_bit(WRITE_PENDING, &con->flags));
- WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags));
+ WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags));
+ WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags));
}
}
@@ -2482,7 +2492,7 @@ void ceph_con_send(struct ceph_connectio
/* if there wasn't anything waiting to send before, queue
* new work */
- if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
+ if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0)
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_send);
@@ -2571,8 +2581,8 @@ void ceph_con_keepalive(struct ceph_conn
mutex_lock(&con->mutex);
clear_standby(con);
mutex_unlock(&con->mutex);
- if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 &&
- test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
+ if (test_and_set_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags) == 0 &&
+ test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0)
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_keepalive);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 928443cd9644e7cfd46f687dbeffda2d1a357ff9)
A ceph_connection holds a mixture of connection state (as in "state
machine" state) and connection flags in a single "state" field. To
make the distinction more clear, define a new "flags" field and use
it rather than the "state" field to hold Boolean flag values.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil<[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 18 +++++++++-----
net/ceph/messenger.c | 50 ++++++++++++++++++++---------------------
2 files changed, 37 insertions(+), 31 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -103,20 +103,25 @@ struct ceph_msg_pos {
#define MAX_DELAY_INTERVAL (5 * 60 * HZ)
/*
- * ceph_connection state bit flags
+ * ceph_connection flag bits
*/
+
#define LOSSYTX 0 /* we can close channel or drop messages on errors */
-#define CONNECTING 1
-#define NEGOTIATING 2
#define KEEPALIVE_PENDING 3
#define WRITE_PENDING 4 /* we have data ready to send */
+#define SOCK_CLOSED 11 /* socket state changed to closed */
+#define BACKOFF 15
+
+/*
+ * ceph_connection states
+ */
+#define CONNECTING 1
+#define NEGOTIATING 2
#define STANDBY 8 /* no outgoing messages, socket closed. we keep
* the ceph_connection around to maintain shared
* state with the peer. */
#define CLOSED 10 /* we've closed the connection */
-#define SOCK_CLOSED 11 /* socket state changed to closed */
#define OPENING 13 /* open connection w/ (possibly new) peer */
-#define BACKOFF 15
/*
* A single connection with another host.
@@ -133,7 +138,8 @@ struct ceph_connection {
struct ceph_messenger *msgr;
struct socket *sock;
- unsigned long state; /* connection state (see flags above) */
+ unsigned long flags;
+ unsigned long state;
const char *error_msg; /* error message, if any */
struct ceph_entity_addr peer_addr; /* peer address */
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -176,7 +176,7 @@ static void ceph_sock_write_space(struct
* buffer. See net/ipv4/tcp_input.c:tcp_check_space()
* and net/core/stream.c:sk_stream_write_space().
*/
- if (test_bit(WRITE_PENDING, &con->state)) {
+ if (test_bit(WRITE_PENDING, &con->flags)) {
if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) {
dout("%s %p queueing write work\n", __func__, con);
clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
@@ -203,7 +203,7 @@ static void ceph_sock_state_change(struc
dout("%s TCP_CLOSE\n", __func__);
case TCP_CLOSE_WAIT:
dout("%s TCP_CLOSE_WAIT\n", __func__);
- if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) {
+ if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) {
if (test_bit(CONNECTING, &con->state))
con->error_msg = "connection failed";
else
@@ -395,9 +395,9 @@ void ceph_con_close(struct ceph_connecti
ceph_pr_addr(&con->peer_addr.in_addr));
set_bit(CLOSED, &con->state); /* in case there's queued work */
clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */
- clear_bit(LOSSYTX, &con->state); /* so we retry next connect */
- clear_bit(KEEPALIVE_PENDING, &con->state);
- clear_bit(WRITE_PENDING, &con->state);
+ clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */
+ clear_bit(KEEPALIVE_PENDING, &con->flags);
+ clear_bit(WRITE_PENDING, &con->flags);
mutex_lock(&con->mutex);
reset_connection(con);
con->peer_global_seq = 0;
@@ -618,7 +618,7 @@ static void prepare_write_message(struct
prepare_write_message_footer(con);
}
- set_bit(WRITE_PENDING, &con->state);
+ set_bit(WRITE_PENDING, &con->flags);
}
/*
@@ -639,7 +639,7 @@ static void prepare_write_ack(struct cep
&con->out_temp_ack);
con->out_more = 1; /* more will follow.. eventually.. */
- set_bit(WRITE_PENDING, &con->state);
+ set_bit(WRITE_PENDING, &con->flags);
}
/*
@@ -650,7 +650,7 @@ static void prepare_write_keepalive(stru
dout("prepare_write_keepalive %p\n", con);
con_out_kvec_reset(con);
con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive);
- set_bit(WRITE_PENDING, &con->state);
+ set_bit(WRITE_PENDING, &con->flags);
}
/*
@@ -679,7 +679,7 @@ static struct ceph_auth_handshake *get_c
if (IS_ERR(auth))
return auth;
- if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags))
return ERR_PTR(-EAGAIN);
con->auth_reply_buf = auth->authorizer_reply_buf;
@@ -699,7 +699,7 @@ static void prepare_write_banner(struct
&con->msgr->my_enc_addr);
con->out_more = 0;
- set_bit(WRITE_PENDING, &con->state);
+ set_bit(WRITE_PENDING, &con->flags);
}
static int prepare_write_connect(struct ceph_connection *con)
@@ -749,7 +749,7 @@ static int prepare_write_connect(struct
auth->authorizer_buf);
con->out_more = 0;
- set_bit(WRITE_PENDING, &con->state);
+ set_bit(WRITE_PENDING, &con->flags);
return 0;
}
@@ -1496,7 +1496,7 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_reply.connect_seq));
if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
- set_bit(LOSSYTX, &con->state);
+ set_bit(LOSSYTX, &con->flags);
prepare_read_tag(con);
break;
@@ -1937,14 +1937,14 @@ do_next:
prepare_write_ack(con);
goto more;
}
- if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) {
+ if (test_and_clear_bit(KEEPALIVE_PENDING, &con->flags)) {
prepare_write_keepalive(con);
goto more;
}
}
/* Nothing to do! */
- clear_bit(WRITE_PENDING, &con->state);
+ clear_bit(WRITE_PENDING, &con->flags);
dout("try_write nothing else to write.\n");
ret = 0;
out:
@@ -2110,7 +2110,7 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
- if (test_and_clear_bit(BACKOFF, &con->state)) {
+ if (test_and_clear_bit(BACKOFF, &con->flags)) {
dout("con_work %p backing off\n", con);
if (queue_delayed_work(ceph_msgr_wq, &con->work,
round_jiffies_relative(con->delay))) {
@@ -2139,7 +2139,7 @@ restart:
con_close_socket(con);
}
- if (test_and_clear_bit(SOCK_CLOSED, &con->state))
+ if (test_and_clear_bit(SOCK_CLOSED, &con->flags))
goto fault;
ret = try_read(con);
@@ -2178,7 +2178,7 @@ static void ceph_fault(struct ceph_conne
dout("fault %p state %lu to peer %s\n",
con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
- if (test_bit(LOSSYTX, &con->state)) {
+ if (test_bit(LOSSYTX, &con->flags)) {
dout("fault on LOSSYTX channel\n");
goto out;
}
@@ -2200,9 +2200,9 @@ static void ceph_fault(struct ceph_conne
/* If there are no messages queued or keepalive pending, place
* the connection in a STANDBY state */
if (list_empty(&con->out_queue) &&
- !test_bit(KEEPALIVE_PENDING, &con->state)) {
+ !test_bit(KEEPALIVE_PENDING, &con->flags)) {
dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con);
- clear_bit(WRITE_PENDING, &con->state);
+ clear_bit(WRITE_PENDING, &con->flags);
set_bit(STANDBY, &con->state);
} else {
/* retry after a delay. */
@@ -2226,7 +2226,7 @@ static void ceph_fault(struct ceph_conne
* that when con_work restarts we schedule the
* delay then.
*/
- set_bit(BACKOFF, &con->state);
+ set_bit(BACKOFF, &con->flags);
}
}
@@ -2282,8 +2282,8 @@ static void clear_standby(struct ceph_co
mutex_lock(&con->mutex);
dout("clear_standby %p and ++connect_seq\n", con);
con->connect_seq++;
- WARN_ON(test_bit(WRITE_PENDING, &con->state));
- WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state));
+ WARN_ON(test_bit(WRITE_PENDING, &con->flags));
+ WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags));
mutex_unlock(&con->mutex);
}
}
@@ -2321,7 +2321,7 @@ void ceph_con_send(struct ceph_connectio
/* if there wasn't anything waiting to send before, queue
* new work */
clear_standby(con);
- if (test_and_set_bit(WRITE_PENDING, &con->state) == 0)
+ if (test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_send);
@@ -2388,8 +2388,8 @@ void ceph_con_keepalive(struct ceph_conn
{
dout("con_keepalive %p\n", con);
clear_standby(con);
- if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 &&
- test_and_set_bit(WRITE_PENDING, &con->state) == 0)
+ if (test_and_set_bit(KEEPALIVE_PENDING, &con->flags) == 0 &&
+ test_and_set_bit(WRITE_PENDING, &con->flags) == 0)
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_keepalive);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Yan, Zheng" <[email protected]>
(cherry picked from commit 43643528cce60ca184fe8197efa8e8da7c89a037)
(cherry picked from commit b132cf4c733f91bb4dd2277ea049243cf16e8b66)
The bug can cause NULL pointer dereference in write_partial_msg_pages
Signed-off-by: Zheng Yan <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -563,6 +563,10 @@ static void prepare_write_message(struct
m->hdr.seq = cpu_to_le64(++con->out_seq);
m->needs_out_seq = false;
}
+#ifdef CONFIG_BLOCK
+ else
+ m->bio_iter = NULL;
+#endif
dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
m, con->out_seq, le16_to_cpu(m->hdr.type),
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Artem Bityutskiy <[email protected]>
commit 98a1eebda3cb2a84ecf1f219bb3a95769033d1bf upstream.
This commit is a preparation for a subsequent bugfix. We introduce a
counter for categorized lprops.
Signed-off-by: Artem Bityutskiy <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ubifs/lprops.c | 6 ++++++
fs/ubifs/ubifs.h | 3 +++
2 files changed, 9 insertions(+)
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info
default:
ubifs_assert(0);
}
+
lprops->flags &= ~LPROPS_CAT_MASK;
lprops->flags |= cat;
+ c->in_a_category_cnt += 1;
+ ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
}
/**
@@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct
default:
ubifs_assert(0);
}
+
+ c->in_a_category_cnt -= 1;
+ ubifs_assert(c->in_a_category_cnt >= 0);
}
/**
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1184,6 +1184,8 @@ struct ubifs_debug_info;
* @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
* @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
* @freeable_cnt: number of freeable LEBs in @freeable_list
+ * @in_a_category_cnt: count of lprops which are in a certain category, which
+ * basically meants that they were loaded from the flash
*
* @ltab_lnum: LEB number of LPT's own lprops table
* @ltab_offs: offset of LPT's own lprops table
@@ -1413,6 +1415,7 @@ struct ubifs_info {
struct list_head freeable_list;
struct list_head frdi_idx_list;
int freeable_cnt;
+ int in_a_category_cnt;
int ltab_lnum;
int ltab_offs;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rusty Russell <[email protected]>
commit 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 upstream.
Masaki found and patched a kallsyms issue: the last symbol in a
module's symtab wasn't transferred. This is because we manually copy
the zero'th entry (which is always empty) then copy the rest in a loop
starting at 1, though from src[0]. His fix was minimal, I prefer to
rewrite the loops in more standard form.
There are two loops: one to get the size, and one to copy. Make these
identical: always count entry 0 and any defined symbol in an allocated
non-init section.
This bug exists since the following commit was introduced.
module: reduce symbol table for loaded modules (v2)
commit: 4a4962263f07d14660849ec134ee42b63e95ea9a
LKML: http://lkml.org/lkml/2012/10/24/27
Reported-by: Masaki Kimura <[email protected]>
Signed-off-by: Rusty Russell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
kernel/module.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2273,12 +2273,17 @@ static void layout_symtab(struct module
src = (void *)info->hdr + symsect->sh_offset;
nsrc = symsect->sh_size / sizeof(*src);
+ /* strtab always starts with a nul, so offset 0 is the empty string. */
+ strtab_size = 1;
+
/* Compute total space required for the core symbols' strtab. */
- for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
- if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
- strtab_size += strlen(&info->strtab[src->st_name]) + 1;
+ for (ndst = i = 0; i < nsrc; i++) {
+ if (i == 0 ||
+ is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+ strtab_size += strlen(&info->strtab[src[i].st_name])+1;
ndst++;
}
+ }
/* Append room for core symbols at end of core part. */
info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
@@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *
mod->core_symtab = dst = mod->module_core + info->symoffs;
mod->core_strtab = s = mod->module_core + info->stroffs;
src = mod->symtab;
- *dst = *src;
*s++ = 0;
- for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
- if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
- continue;
-
- dst[ndst] = *src;
- dst[ndst++].st_name = s - mod->core_strtab;
- s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
+ for (ndst = i = 0; i < mod->num_symtab; i++) {
+ if (i == 0 ||
+ is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+ dst[ndst] = src[i];
+ dst[ndst++].st_name = s - mod->core_strtab;
+ s += strlcpy(s, &mod->strtab[src[i].st_name],
+ KSYM_NAME_LEN) + 1;
+ }
}
mod->core_num_syms = ndst;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugh Dickins <[email protected]>
commit 0f3c42f522dc1ad7e27affc0a4aa8c790bce0a66 upstream.
Under a particular load on one machine, I have hit shmem_evict_inode()'s
BUG_ON(inode->i_blocks), enough times to narrow it down to a particular
race between swapout and eviction.
It comes from the "if (freed > 0)" asymmetry in shmem_recalc_inode(),
and the lack of coherent locking between mapping's nrpages and shmem's
swapped count. There's a window in shmem_writepage(), between lowering
nrpages in shmem_delete_from_page_cache() and then raising swapped
count, when the freed count appears to be +1 when it should be 0, and
then the asymmetry stops it from being corrected with -1 before hitting
the BUG.
One answer is coherent locking: using tree_lock throughout, without
info->lock; reasonable, but the raw_spin_lock in percpu_counter_add() on
used_blocks makes that messier than expected. Another answer may be a
further effort to eliminate the weird shmem_recalc_inode() altogether,
but previous attempts at that failed.
So far undecided, but for now change the BUG_ON to WARN_ON: in usual
circumstances it remains a useful consistency check.
Signed-off-by: Hugh Dickins <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/shmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -595,7 +595,7 @@ static void shmem_evict_inode(struct ino
kfree(xattr->name);
kfree(xattr);
}
- BUG_ON(inode->i_blocks);
+ WARN_ON(inode->i_blocks);
shmem_free_inode(inode->i_sb);
end_writeback(inode);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 6eb43f4b5a2a74599b4ff17a97c03a342327ca65)
Reflects ceph.git commit 46d63d98434b3bc9dad2fc9ab23cbaedc3bcb0e4.
Reported-by: Alexander Lyakas <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/crush/crush.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/ceph/crush/crush.c
+++ b/net/ceph/crush/crush.c
@@ -85,6 +85,8 @@ void crush_destroy_bucket_list(struct cr
void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
{
+ kfree(b->h.perm);
+ kfree(b->h.items);
kfree(b->node_weights);
kfree(b);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit fd154f3c75465abd83b7a395033e3755908a1e6e)
This is a nit, but prepare_write_message() sets the FOOTER_COMPLETE
flag before the CRC for the data portion (recorded in the footer)
has been completely computed. Hold off setting the complete flag
until we've decided it's ready to send.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -592,6 +592,8 @@ static void prepare_write_message_footer
struct ceph_msg *m = con->out_msg;
int v = con->out_kvec_left;
+ m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE;
+
dout("prepare_write_message_footer %p\n", con);
con->out_kvec_is_msg = true;
con->out_kvec[v].iov_base = &m->footer;
@@ -665,7 +667,7 @@ static void prepare_write_message(struct
/* fill in crc (except data pages), footer */
crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc));
con->out_msg->hdr.crc = cpu_to_le32(crc);
- con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE;
+ con->out_msg->footer.flags = 0;
crc = crc32c(0, m->front.iov_base, m->front.iov_len);
con->out_msg->footer.front_crc = cpu_to_le32(crc);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 8dacc7da69a491c515851e68de6036f21b5663ce)
Use a simple set of 6 enumerated values for the socket states (CON_STATE_*)
and use those instead of the state bits. All of the con->state checks are
now under the protection of the con mutex, so this is safe. It also
simplifies many of the state checks because we can check for anything other
than the expected state instead of various bits for races we can think of.
This appears to hold up well to stress testing both with and without socket
failure injection on the server side.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 12 ---
net/ceph/messenger.c | 130 +++++++++++++++++++++--------------------
2 files changed, 68 insertions(+), 74 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -117,18 +117,6 @@ struct ceph_msg_pos {
#define BACKOFF 15
/*
- * ceph_connection states
- */
-#define CONNECTING 1
-#define NEGOTIATING 2
-#define CONNECTED 5
-#define STANDBY 8 /* no outgoing messages, socket closed. we keep
- * the ceph_connection around to maintain shared
- * state with the peer. */
-#define CLOSED 10 /* we've closed the connection */
-#define OPENING 13 /* open connection w/ (possibly new) peer */
-
-/*
* A single connection with another host.
*
* We maintain a queue of outgoing messages, and some session state to
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -77,6 +77,17 @@
#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */
#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */
+/*
+ * connection states
+ */
+#define CON_STATE_CLOSED 1 /* -> PREOPEN */
+#define CON_STATE_PREOPEN 2 /* -> CONNECTING, CLOSED */
+#define CON_STATE_CONNECTING 3 /* -> NEGOTIATING, CLOSED */
+#define CON_STATE_NEGOTIATING 4 /* -> OPEN, CLOSED */
+#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */
+#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */
+
+
/* static tag bytes (protocol control messages) */
static char tag_msg = CEPH_MSGR_TAG_MSG;
static char tag_ack = CEPH_MSGR_TAG_ACK;
@@ -503,11 +514,7 @@ void ceph_con_close(struct ceph_connecti
mutex_lock(&con->mutex);
dout("con_close %p peer %s\n", con,
ceph_pr_addr(&con->peer_addr.in_addr));
- clear_bit(NEGOTIATING, &con->state);
- clear_bit(CONNECTING, &con->state);
- clear_bit(CONNECTED, &con->state);
- clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */
- set_bit(CLOSED, &con->state);
+ con->state = CON_STATE_CLOSED;
clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */
clear_bit(KEEPALIVE_PENDING, &con->flags);
@@ -530,8 +537,9 @@ void ceph_con_open(struct ceph_connectio
{
mutex_lock(&con->mutex);
dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
- set_bit(OPENING, &con->state);
- WARN_ON(!test_and_clear_bit(CLOSED, &con->state));
+
+ BUG_ON(con->state != CON_STATE_CLOSED);
+ con->state = CON_STATE_PREOPEN;
con->peer_name.type = (__u8) entity_type;
con->peer_name.num = cpu_to_le64(entity_num);
@@ -571,7 +579,7 @@ void ceph_con_init(struct ceph_connectio
INIT_LIST_HEAD(&con->out_sent);
INIT_DELAYED_WORK(&con->work, con_work);
- set_bit(CLOSED, &con->state);
+ con->state = CON_STATE_CLOSED;
}
EXPORT_SYMBOL(ceph_con_init);
@@ -809,27 +817,21 @@ static struct ceph_auth_handshake *get_c
if (!con->ops->get_authorizer) {
con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
con->out_connect.authorizer_len = 0;
-
return NULL;
}
/* Can't hold the mutex while getting authorizer */
-
mutex_unlock(&con->mutex);
-
auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry);
-
mutex_lock(&con->mutex);
if (IS_ERR(auth))
return auth;
- if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->flags))
+ if (con->state != CON_STATE_NEGOTIATING)
return ERR_PTR(-EAGAIN);
con->auth_reply_buf = auth->authorizer_reply_buf;
con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
-
-
return auth;
}
@@ -1484,7 +1486,8 @@ static int process_banner(struct ceph_co
static void fail_protocol(struct ceph_connection *con)
{
reset_connection(con);
- set_bit(CLOSED, &con->state); /* in case there's queued work */
+ BUG_ON(con->state != CON_STATE_NEGOTIATING);
+ con->state = CON_STATE_CLOSED;
}
static int process_connect(struct ceph_connection *con)
@@ -1558,8 +1561,7 @@ static int process_connect(struct ceph_c
if (con->ops->peer_reset)
con->ops->peer_reset(con);
mutex_lock(&con->mutex);
- if (test_bit(CLOSED, &con->state) ||
- test_bit(OPENING, &con->state))
+ if (con->state != CON_STATE_NEGOTIATING)
return -EAGAIN;
break;
@@ -1605,8 +1607,10 @@ static int process_connect(struct ceph_c
fail_protocol(con);
return -1;
}
- clear_bit(NEGOTIATING, &con->state);
- set_bit(CONNECTED, &con->state);
+
+ BUG_ON(con->state != CON_STATE_NEGOTIATING);
+ con->state = CON_STATE_OPEN;
+
con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
con->connect_seq++;
con->peer_features = server_feat;
@@ -1994,8 +1998,9 @@ more:
dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
/* open the socket first? */
- if (con->sock == NULL) {
- set_bit(CONNECTING, &con->state);
+ if (con->state == CON_STATE_PREOPEN) {
+ BUG_ON(con->sock);
+ con->state = CON_STATE_CONNECTING;
con_out_kvec_reset(con);
prepare_write_banner(con);
@@ -2046,8 +2051,7 @@ more_kvec:
}
do_next:
- if (!test_bit(CONNECTING, &con->state) &&
- !test_bit(NEGOTIATING, &con->state)) {
+ if (con->state == CON_STATE_OPEN) {
/* is anything else pending? */
if (!list_empty(&con->out_queue)) {
prepare_write_message(con);
@@ -2081,29 +2085,19 @@ static int try_read(struct ceph_connecti
{
int ret = -1;
- if (!con->sock)
- return 0;
-
- if (test_bit(STANDBY, &con->state))
+more:
+ dout("try_read start on %p state %lu\n", con, con->state);
+ if (con->state != CON_STATE_CONNECTING &&
+ con->state != CON_STATE_NEGOTIATING &&
+ con->state != CON_STATE_OPEN)
return 0;
- dout("try_read start on %p\n", con);
+ BUG_ON(!con->sock);
-more:
dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag,
con->in_base_pos);
- /*
- * process_connect and process_message drop and re-take
- * con->mutex. make sure we handle a racing close or reopen.
- */
- if (test_bit(CLOSED, &con->state) ||
- test_bit(OPENING, &con->state)) {
- ret = -EAGAIN;
- goto out;
- }
-
- if (test_bit(CONNECTING, &con->state)) {
+ if (con->state == CON_STATE_CONNECTING) {
dout("try_read connecting\n");
ret = read_partial_banner(con);
if (ret <= 0)
@@ -2112,8 +2106,8 @@ more:
if (ret < 0)
goto out;
- clear_bit(CONNECTING, &con->state);
- set_bit(NEGOTIATING, &con->state);
+ BUG_ON(con->state != CON_STATE_CONNECTING);
+ con->state = CON_STATE_NEGOTIATING;
/* Banner is good, exchange connection info */
ret = prepare_write_connect(con);
@@ -2125,7 +2119,7 @@ more:
goto out;
}
- if (test_bit(NEGOTIATING, &con->state)) {
+ if (con->state == CON_STATE_NEGOTIATING) {
dout("try_read negotiating\n");
ret = read_partial_connect(con);
if (ret <= 0)
@@ -2136,6 +2130,8 @@ more:
goto more;
}
+ BUG_ON(con->state != CON_STATE_OPEN);
+
if (con->in_base_pos < 0) {
/*
* skipping + discarding content.
@@ -2169,8 +2165,8 @@ more:
prepare_read_ack(con);
break;
case CEPH_MSGR_TAG_CLOSE:
- clear_bit(CONNECTED, &con->state);
- set_bit(CLOSED, &con->state); /* fixme */
+ con_close_socket(con);
+ con->state = CON_STATE_CLOSED;
goto out;
default:
goto bad_tag;
@@ -2246,14 +2242,21 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
- if (test_and_clear_bit(CONNECTED, &con->state))
- con->error_msg = "socket closed";
- else if (test_and_clear_bit(NEGOTIATING, &con->state))
- con->error_msg = "negotiation failed";
- else if (test_and_clear_bit(CONNECTING, &con->state))
+ switch (con->state) {
+ case CON_STATE_CONNECTING:
con->error_msg = "connection failed";
- else
+ break;
+ case CON_STATE_NEGOTIATING:
+ con->error_msg = "negotiation failed";
+ break;
+ case CON_STATE_OPEN:
+ con->error_msg = "socket closed";
+ break;
+ default:
+ dout("unrecognized con state %d\n", (int)con->state);
con->error_msg = "unrecognized con state";
+ BUG();
+ }
goto fault;
}
@@ -2271,17 +2274,16 @@ restart:
}
}
- if (test_bit(STANDBY, &con->state)) {
+ if (con->state == CON_STATE_STANDBY) {
dout("con_work %p STANDBY\n", con);
goto done;
}
- if (test_bit(CLOSED, &con->state)) {
+ if (con->state == CON_STATE_CLOSED) {
dout("con_work %p CLOSED\n", con);
BUG_ON(con->sock);
goto done;
}
- if (test_and_clear_bit(OPENING, &con->state)) {
- /* reopen w/ new peer */
+ if (con->state == CON_STATE_PREOPEN) {
dout("con_work OPENING\n");
BUG_ON(con->sock);
}
@@ -2328,13 +2330,15 @@ static void ceph_fault(struct ceph_conne
dout("fault %p state %lu to peer %s\n",
con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
- if (test_bit(CLOSED, &con->state))
- goto out_unlock;
+ BUG_ON(con->state != CON_STATE_CONNECTING &&
+ con->state != CON_STATE_NEGOTIATING &&
+ con->state != CON_STATE_OPEN);
con_close_socket(con);
if (test_bit(LOSSYTX, &con->flags)) {
- dout("fault on LOSSYTX channel\n");
+ dout("fault on LOSSYTX channel, marking CLOSED\n");
+ con->state = CON_STATE_CLOSED;
goto out_unlock;
}
@@ -2355,9 +2359,10 @@ static void ceph_fault(struct ceph_conne
!test_bit(KEEPALIVE_PENDING, &con->flags)) {
dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con);
clear_bit(WRITE_PENDING, &con->flags);
- set_bit(STANDBY, &con->state);
+ con->state = CON_STATE_STANDBY;
} else {
/* retry after a delay. */
+ con->state = CON_STATE_PREOPEN;
if (con->delay == 0)
con->delay = BASE_DELAY_INTERVAL;
else if (con->delay < MAX_DELAY_INTERVAL)
@@ -2431,8 +2436,9 @@ EXPORT_SYMBOL(ceph_messenger_init);
static void clear_standby(struct ceph_connection *con)
{
/* come back from STANDBY? */
- if (test_and_clear_bit(STANDBY, &con->state)) {
+ if (con->state == CON_STATE_STANDBY) {
dout("clear_standby %p and ++connect_seq\n", con);
+ con->state = CON_STATE_PREOPEN;
con->connect_seq++;
WARN_ON(test_bit(WRITE_PENDING, &con->flags));
WARN_ON(test_bit(KEEPALIVE_PENDING, &con->flags));
@@ -2451,7 +2457,7 @@ void ceph_con_send(struct ceph_connectio
mutex_lock(&con->mutex);
- if (test_bit(CLOSED, &con->state)) {
+ if (con->state == CON_STATE_CLOSED) {
dout("con_send %p closed, dropping %p\n", con, msg);
ceph_msg_put(msg);
mutex_unlock(&con->mutex);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jussi Kivilinna <[email protected]>
commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream.
cryptd_queue_worker attempts to prevent simultaneous accesses to crypto
workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable.
However cryptd_enqueue_request might be called from softirq context,
so add local_bh_disable/local_bh_enable to prevent data corruption and
panics.
Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2
v2:
- Disable software interrupts instead of hardware interrupts
Reported-by: Gurucharan Shetty <[email protected]>
Signed-off-by: Jussi Kivilinna <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
crypto/cryptd.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct w
struct crypto_async_request *req, *backlog;
cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
- /* Only handle one request at a time to avoid hogging crypto
- * workqueue. preempt_disable/enable is used to prevent
- * being preempted by cryptd_enqueue_request() */
+ /*
+ * Only handle one request at a time to avoid hogging crypto workqueue.
+ * preempt_disable/enable is used to prevent being preempted by
+ * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
+ * cryptd_enqueue_request() being accessed from software interrupts.
+ */
+ local_bh_disable();
preempt_disable();
backlog = crypto_get_backlog(&cpu_queue->queue);
req = crypto_dequeue_request(&cpu_queue->queue);
preempt_enable();
+ local_bh_enable();
if (!req)
return;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit a5988c490ef66cb04ea2f610681949b25c773b3c)
Once a connection is fully initialized, it is really in a CLOSED
state, so make that explicit by setting the bit in its state field.
It is possible for a connection in NEGOTIATING state to get a
failure, leading to ceph_fault() and ultimately ceph_con_close().
Clear that bits if it is set in that case, to reflect that the
connection truly is closed and is no longer participating in a
connect sequence.
Issue a warning if ceph_con_open() is called on a connection that
is not in CLOSED state.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -454,11 +454,14 @@ void ceph_con_close(struct ceph_connecti
{
dout("con_close %p peer %s\n", con,
ceph_pr_addr(&con->peer_addr.in_addr));
- set_bit(CLOSED, &con->state); /* in case there's queued work */
+ clear_bit(NEGOTIATING, &con->state);
clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */
+ set_bit(CLOSED, &con->state);
+
clear_bit(LOSSYTX, &con->flags); /* so we retry next connect */
clear_bit(KEEPALIVE_PENDING, &con->flags);
clear_bit(WRITE_PENDING, &con->flags);
+
mutex_lock(&con->mutex);
reset_connection(con);
con->peer_global_seq = 0;
@@ -475,7 +478,8 @@ void ceph_con_open(struct ceph_connectio
{
dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
set_bit(OPENING, &con->state);
- clear_bit(CLOSED, &con->state);
+ WARN_ON(!test_and_clear_bit(CLOSED, &con->state));
+
memcpy(&con->peer_addr, addr, sizeof(*addr));
con->delay = 0; /* reset backoff memory */
queue_con(con);
@@ -530,6 +534,8 @@ void ceph_con_init(struct ceph_messenger
INIT_LIST_HEAD(&con->out_queue);
INIT_LIST_HEAD(&con->out_sent);
INIT_DELAYED_WORK(&con->work, con_work);
+
+ set_bit(CLOSED, &con->state);
}
EXPORT_SYMBOL(ceph_con_init);
@@ -1937,14 +1943,15 @@ more:
/* open the socket first? */
if (con->sock == NULL) {
+ clear_bit(NEGOTIATING, &con->state);
+ set_bit(CONNECTING, &con->state);
+
con_out_kvec_reset(con);
prepare_write_banner(con);
ret = prepare_write_connect(con);
if (ret < 0)
goto out;
prepare_read_banner(con);
- set_bit(CONNECTING, &con->state);
- clear_bit(NEGOTIATING, &con->state);
BUG_ON(con->in_msg);
con->in_tag = CEPH_MSGR_TAG_READY;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 8921d114f5574c6da2cdd00749d185633ecf88f3)
ceph_con_revoke_message() is passed both a message and a ceph
connection. A ceph_msg allocated for incoming messages on a
connection always has a pointer to that connection, so there's no
need to provide the connection when revoking such a message.
Note that the existing logic does not preclude the message supplied
being a null/bogus message pointer. The only user of this interface
is the OSD client, and the only value an osd client passes is a
request's r_reply field. That is always non-null (except briefly in
an error path in ceph_osdc_alloc_request(), and that drops the
only reference so the request won't ever have a reply to revoke).
So we can safely assume the passed-in message is non-null, but add a
BUG_ON() to make it very obvious we are imposing this restriction.
Rename the function ceph_msg_revoke_incoming() to reflect that it is
really an operation on an incoming message.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 4 ++--
net/ceph/messenger.c | 22 ++++++++++++++++------
net/ceph/osd_client.c | 9 ++++-----
3 files changed, 22 insertions(+), 13 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -233,8 +233,8 @@ extern void ceph_con_close(struct ceph_c
extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg);
extern void ceph_msg_revoke(struct ceph_msg *msg);
-extern void ceph_con_revoke_message(struct ceph_connection *con,
- struct ceph_msg *msg);
+extern void ceph_msg_revoke_incoming(struct ceph_msg *msg);
+
extern void ceph_con_keepalive(struct ceph_connection *con);
extern struct ceph_connection *ceph_con_get(struct ceph_connection *con);
extern void ceph_con_put(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2460,17 +2460,27 @@ void ceph_msg_revoke(struct ceph_msg *ms
/*
* Revoke a message that we may be reading data into
*/
-void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg)
+void ceph_msg_revoke_incoming(struct ceph_msg *msg)
{
+ struct ceph_connection *con;
+
+ BUG_ON(msg == NULL);
+ if (!msg->con) {
+ dout("%s msg %p null con\n", __func__, msg);
+
+ return; /* Message not in our possession */
+ }
+
+ con = msg->con;
mutex_lock(&con->mutex);
- if (con->in_msg && con->in_msg == msg) {
+ if (con->in_msg == msg) {
unsigned front_len = le32_to_cpu(con->in_hdr.front_len);
unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len);
unsigned data_len = le32_to_cpu(con->in_hdr.data_len);
/* skip rest of message */
- dout("con_revoke_pages %p msg %p revoked\n", con, msg);
- con->in_base_pos = con->in_base_pos -
+ dout("%s %p msg %p revoked\n", __func__, con, msg);
+ con->in_base_pos = con->in_base_pos -
sizeof(struct ceph_msg_header) -
front_len -
middle_len -
@@ -2481,8 +2491,8 @@ void ceph_con_revoke_message(struct ceph
con->in_tag = CEPH_MSGR_TAG_READY;
con->in_seq++;
} else {
- dout("con_revoke_pages %p msg %p pages %p no-op\n",
- con, con->in_msg, msg);
+ dout("%s %p in_msg %p msg %p no-op\n",
+ __func__, con, con->in_msg, msg);
}
mutex_unlock(&con->mutex);
}
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -140,10 +140,9 @@ void ceph_osdc_release_request(struct kr
if (req->r_request)
ceph_msg_put(req->r_request);
if (req->r_con_filling_msg) {
- dout("release_request revoking pages %p from con %p\n",
+ dout("%s revoking pages %p from con %p\n", __func__,
req->r_pages, req->r_con_filling_msg);
- ceph_con_revoke_message(req->r_con_filling_msg,
- req->r_reply);
+ ceph_msg_revoke_incoming(req->r_reply);
req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
}
if (req->r_reply)
@@ -2022,9 +2021,9 @@ static struct ceph_msg *get_reply(struct
}
if (req->r_con_filling_msg) {
- dout("get_reply revoking msg %p from old con %p\n",
+ dout("%s revoking msg %p from old con %p\n", __func__,
req->r_reply, req->r_con_filling_msg);
- ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply);
+ ceph_msg_revoke_incoming(req->r_reply);
req->r_con_filling_msg->ops->put(req->r_con_filling_msg);
req->r_con_filling_msg = NULL;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit ae24c3191ba2ab03ec6b4be323e730e00404b4b6 upstream.
Several bug reports suggest that the forcibly resetting IEC958 status
bits is required for AD codecs to get the SPDIF output working
properly after changing streams.
Original fix credit to Javeed Shaikh.
BugLink: https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/359361
Reported-by: Robin Kreis <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
sound/pci/hda/patch_analog.c | 1 +
1 file changed, 1 insertion(+)
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -544,6 +544,7 @@ static int ad198x_build_pcms(struct hda_
if (spec->multiout.dig_out_nid) {
info++;
codec->num_pcms++;
+ codec->spdif_status_reset = 1;
info->name = "AD198x Digital";
info->pcm_type = HDA_PCM_TYPE_SPDIF;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 15d9882c336db2db73ccf9871ae2398e452f694c)
A ceph client has a pointer to a ceph messenger structure in it.
There is always exactly one ceph messenger for a ceph client, so
there is no need to allocate it separate from the ceph client
structure.
Switch the ceph_client structure to embed its ceph_messenger
structure.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 2 +-
include/linux/ceph/libceph.h | 2 +-
include/linux/ceph/messenger.h | 9 +++++----
net/ceph/ceph_common.c | 18 +++++-------------
net/ceph/messenger.c | 30 +++++++++---------------------
net/ceph/mon_client.c | 6 +++---
net/ceph/osd_client.c | 4 ++--
7 files changed, 26 insertions(+), 45 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -394,7 +394,7 @@ static struct ceph_mds_session *register
s->s_seq = 0;
mutex_init(&s->s_mutex);
- ceph_con_init(mdsc->fsc->client->msgr, &s->s_con);
+ ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con);
s->s_con.private = s;
s->s_con.ops = &mds_con_ops;
s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -132,7 +132,7 @@ struct ceph_client {
u32 supported_features;
u32 required_features;
- struct ceph_messenger *msgr; /* messenger instance */
+ struct ceph_messenger msgr; /* messenger instance */
struct ceph_mon_client monc;
struct ceph_osd_client osdc;
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -203,10 +203,11 @@ extern int ceph_msgr_init(void);
extern void ceph_msgr_exit(void);
extern void ceph_msgr_flush(void);
-extern struct ceph_messenger *ceph_messenger_create(
- struct ceph_entity_addr *myaddr,
- u32 features, u32 required);
-extern void ceph_messenger_destroy(struct ceph_messenger *);
+extern void ceph_messenger_init(struct ceph_messenger *msgr,
+ struct ceph_entity_addr *myaddr,
+ u32 supported_features,
+ u32 required_features,
+ bool nocrc);
extern void ceph_con_init(struct ceph_messenger *msgr,
struct ceph_connection *con);
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -468,19 +468,15 @@ struct ceph_client *ceph_create_client(s
/* msgr */
if (ceph_test_opt(client, MYIP))
myaddr = &client->options->my_addr;
- client->msgr = ceph_messenger_create(myaddr,
- client->supported_features,
- client->required_features);
- if (IS_ERR(client->msgr)) {
- err = PTR_ERR(client->msgr);
- goto fail;
- }
- client->msgr->nocrc = ceph_test_opt(client, NOCRC);
+ ceph_messenger_init(&client->msgr, myaddr,
+ client->supported_features,
+ client->required_features,
+ ceph_test_opt(client, NOCRC));
/* subsystems */
err = ceph_monc_init(&client->monc, client);
if (err < 0)
- goto fail_msgr;
+ goto fail;
err = ceph_osdc_init(&client->osdc, client);
if (err < 0)
goto fail_monc;
@@ -489,8 +485,6 @@ struct ceph_client *ceph_create_client(s
fail_monc:
ceph_monc_stop(&client->monc);
-fail_msgr:
- ceph_messenger_destroy(client->msgr);
fail:
kfree(client);
return ERR_PTR(err);
@@ -508,8 +502,6 @@ void ceph_destroy_client(struct ceph_cli
ceph_debugfs_client_cleanup(client);
- ceph_messenger_destroy(client->msgr);
-
ceph_destroy_options(client->options);
kfree(client);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2249,18 +2249,14 @@ out:
/*
- * create a new messenger instance
+ * initialize a new messenger instance
*/
-struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr,
- u32 supported_features,
- u32 required_features)
+void ceph_messenger_init(struct ceph_messenger *msgr,
+ struct ceph_entity_addr *myaddr,
+ u32 supported_features,
+ u32 required_features,
+ bool nocrc)
{
- struct ceph_messenger *msgr;
-
- msgr = kzalloc(sizeof(*msgr), GFP_KERNEL);
- if (msgr == NULL)
- return ERR_PTR(-ENOMEM);
-
msgr->supported_features = supported_features;
msgr->required_features = required_features;
@@ -2273,19 +2269,11 @@ struct ceph_messenger *ceph_messenger_cr
msgr->inst.addr.type = 0;
get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce));
encode_my_addr(msgr);
+ msgr->nocrc = nocrc;
- dout("messenger_create %p\n", msgr);
- return msgr;
-}
-EXPORT_SYMBOL(ceph_messenger_create);
-
-void ceph_messenger_destroy(struct ceph_messenger *msgr)
-{
- dout("destroy %p\n", msgr);
- kfree(msgr);
- dout("destroyed messenger %p\n", msgr);
+ dout("%s %p\n", __func__, msgr);
}
-EXPORT_SYMBOL(ceph_messenger_destroy);
+EXPORT_SYMBOL(ceph_messenger_init);
static void clear_standby(struct ceph_connection *con)
{
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -763,7 +763,7 @@ int ceph_monc_init(struct ceph_mon_clien
monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL);
if (!monc->con)
goto out_monmap;
- ceph_con_init(monc->client->msgr, monc->con);
+ ceph_con_init(&monc->client->msgr, monc->con);
monc->con->private = monc;
monc->con->ops = &mon_con_ops;
@@ -888,8 +888,8 @@ static void handle_auth_reply(struct cep
} else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) {
dout("authenticated, starting session\n");
- monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
- monc->client->msgr->inst.name.num =
+ monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
+ monc->client->msgr.inst.name.num =
cpu_to_le64(monc->auth->global_id);
__send_subscribe(monc);
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -639,7 +639,7 @@ static struct ceph_osd *create_osd(struc
INIT_LIST_HEAD(&osd->o_osd_lru);
osd->o_incarnation = 1;
- ceph_con_init(osdc->client->msgr, &osd->o_con);
+ ceph_con_init(&osdc->client->msgr, &osd->o_con);
osd->o_con.private = osd;
osd->o_con.ops = &osd_con_ops;
osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
@@ -1391,7 +1391,7 @@ void ceph_osdc_handle_map(struct ceph_os
epoch, maplen);
newmap = osdmap_apply_incremental(&p, next,
osdc->osdmap,
- osdc->client->msgr);
+ &osdc->client->msgr);
if (IS_ERR(newmap)) {
err = PTR_ERR(newmap);
goto bad;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit df6ad1f97342ebc4270128222e896541405eecdb)
Move init_bio_iter() and iter_bio_next() up in their source file so
the'll be defined before they're needed.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 50 +++++++++++++++++++++++++-------------------------
1 file changed, 25 insertions(+), 25 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -565,6 +565,31 @@ static void con_out_kvec_add(struct ceph
con->out_kvec_bytes += size;
}
+#ifdef CONFIG_BLOCK
+static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg)
+{
+ if (!bio) {
+ *iter = NULL;
+ *seg = 0;
+ return;
+ }
+ *iter = bio;
+ *seg = bio->bi_idx;
+}
+
+static void iter_bio_next(struct bio **bio_iter, int *seg)
+{
+ if (*bio_iter == NULL)
+ return;
+
+ BUG_ON(*seg >= (*bio_iter)->bi_vcnt);
+
+ (*seg)++;
+ if (*seg == (*bio_iter)->bi_vcnt)
+ init_bio_iter((*bio_iter)->bi_next, bio_iter, seg);
+}
+#endif
+
static void prepare_write_message_data(struct ceph_connection *con)
{
struct ceph_msg *msg = con->out_msg;
@@ -868,31 +893,6 @@ out:
return ret; /* done! */
}
-#ifdef CONFIG_BLOCK
-static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg)
-{
- if (!bio) {
- *iter = NULL;
- *seg = 0;
- return;
- }
- *iter = bio;
- *seg = bio->bi_idx;
-}
-
-static void iter_bio_next(struct bio **bio_iter, int *seg)
-{
- if (*bio_iter == NULL)
- return;
-
- BUG_ON(*seg >= (*bio_iter)->bi_vcnt);
-
- (*seg)++;
- if (*seg == (*bio_iter)->bi_vcnt)
- init_bio_iter((*bio_iter)->bi_next, bio_iter, seg);
-}
-#endif
-
static void out_msg_pos_next(struct ceph_connection *con, struct page *page,
size_t len, size_t sent, bool in_trail)
{
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit a255651d4cad89f1a606edd36135af892ada4f20)
In the create_authorizer method for both the mds and osd clients,
the auth_client->ops pointer is blindly dereferenced. There is no
obvious guarantee that this pointer has been assigned. And
furthermore, even if the ops pointer is non-null there is definitely
no guarantee that the create_authorizer or destroy_authorizer
methods are defined.
Add checks in both routines to make sure they are defined (non-null)
before use. Add similar checks in a few other spots in these files
while we're at it.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 14 ++++++--------
net/ceph/osd_client.c | 15 ++++++++++-----
2 files changed, 16 insertions(+), 13 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3406,16 +3406,14 @@ static int get_authorizer(struct ceph_co
int ret = 0;
if (force_new && auth->authorizer) {
- ac->ops->destroy_authorizer(ac, auth->authorizer);
+ if (ac->ops && ac->ops->destroy_authorizer)
+ ac->ops->destroy_authorizer(ac, auth->authorizer);
auth->authorizer = NULL;
}
- if (auth->authorizer == NULL) {
- if (ac->ops->create_authorizer) {
- ret = ac->ops->create_authorizer(ac,
- CEPH_ENTITY_TYPE_MDS, auth);
- if (ret)
- return ret;
- }
+ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
+ ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth);
+ if (ret)
+ return ret;
}
*proto = ac->protocol;
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -664,10 +664,10 @@ static void put_osd(struct ceph_osd *osd
{
dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
atomic_read(&osd->o_ref) - 1);
- if (atomic_dec_and_test(&osd->o_ref)) {
+ if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) {
struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth;
- if (osd->o_auth.authorizer)
+ if (ac->ops && ac->ops->destroy_authorizer)
ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer);
kfree(osd);
}
@@ -2119,10 +2119,11 @@ static int get_authorizer(struct ceph_co
int ret = 0;
if (force_new && auth->authorizer) {
- ac->ops->destroy_authorizer(ac, auth->authorizer);
+ if (ac->ops && ac->ops->destroy_authorizer)
+ ac->ops->destroy_authorizer(ac, auth->authorizer);
auth->authorizer = NULL;
}
- if (auth->authorizer == NULL) {
+ if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) {
ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth);
if (ret)
return ret;
@@ -2144,6 +2145,10 @@ static int verify_authorizer_reply(struc
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
+ /*
+ * XXX If ac->ops or ac->ops->verify_authorizer_reply is null,
+ * XXX which do we do: succeed or fail?
+ */
return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len);
}
@@ -2153,7 +2158,7 @@ static int invalidate_authorizer(struct
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
- if (ac->ops->invalidate_authorizer)
+ if (ac->ops && ac->ops->invalidate_authorizer)
ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD);
return ceph_monc_validate_auth(&osdc->client->monc);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 36eb71aa57e6a33d61fd90a2fd87f00c6844bc86)
The ceph_con_get/put() helpers manipulate the embedded con ref
count, which isn't used now that ceph_connections are embedded in
other structures.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -414,7 +414,7 @@ static void ceph_msg_remove(struct ceph_
{
list_del_init(&msg->list_head);
BUG_ON(msg->con == NULL);
- ceph_con_put(msg->con);
+ msg->con->ops->put(msg->con);
msg->con = NULL;
ceph_msg_put(msg);
@@ -440,7 +440,7 @@ static void reset_connection(struct ceph
con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
- ceph_con_put(con);
+ con->ops->put(con);
}
con->connect_seq = 0;
@@ -1919,7 +1919,7 @@ static void process_message(struct ceph_
con->in_msg->con = NULL;
msg = con->in_msg;
con->in_msg = NULL;
- ceph_con_put(con);
+ con->ops->put(con);
/* if first message, set peer_name */
if (con->peer_name.type == 0)
@@ -2281,7 +2281,7 @@ static void ceph_fault(struct ceph_conne
con->in_msg->con = NULL;
ceph_msg_put(con->in_msg);
con->in_msg = NULL;
- ceph_con_put(con);
+ con->ops->put(con);
}
/* Requeue anything that hasn't been acked */
@@ -2400,7 +2400,7 @@ void ceph_con_send(struct ceph_connectio
mutex_lock(&con->mutex);
BUG_ON(msg->con != NULL);
- msg->con = ceph_con_get(con);
+ msg->con = con->ops->get(con);
BUG_ON(msg->con == NULL);
BUG_ON(!list_empty(&msg->list_head));
@@ -2436,7 +2436,7 @@ void ceph_msg_revoke(struct ceph_msg *ms
dout("%s %p msg %p - was on queue\n", __func__, con, msg);
list_del_init(&msg->list_head);
BUG_ON(msg->con == NULL);
- ceph_con_put(msg->con);
+ msg->con->ops->put(msg->con);
msg->con = NULL;
msg->hdr.seq = 0;
@@ -2646,7 +2646,7 @@ static bool ceph_con_in_msg_alloc(struct
con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
mutex_lock(&con->mutex);
if (con->in_msg) {
- con->in_msg->con = ceph_con_get(con);
+ con->in_msg->con = con->ops->get(con);
BUG_ON(con->in_msg->con == NULL);
}
if (skip)
@@ -2662,7 +2662,7 @@ static bool ceph_con_in_msg_alloc(struct
type, front_len);
return false;
}
- con->in_msg->con = ceph_con_get(con);
+ con->in_msg->con = con->ops->get(con);
BUG_ON(con->in_msg->con == NULL);
con->in_msg->page_alignment = le16_to_cpu(hdr->data_off);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 588377d6199034c36d335e7df5818b731fea072c)
If ceph_fault() is unable to queue work after a delay, it sets the
BACKOFF connection flag so con_work() will attempt to do so.
In con_work(), when BACKOFF is set, if queue_delayed_work() doesn't
result in newly-queued work, it simply ignores this condition and
proceeds as if no backoff delay were desired. There are two
problems with this--one of which is a bug.
The first problem is simply that the intended behavior is to back
off, and if we aren't able queue the work item to run after a delay
we're not doing that.
The only reason queue_delayed_work() won't queue work is if the
provided work item is already queued. In the messenger, this
means that con_work() is already scheduled to be run again. So
if we simply set the BACKOFF flag again when this occurs, we know
the next con_work() call will again attempt to hold off activity
on the connection until after the delay.
The second problem--the bug--is a leak of a reference count. If
queue_delayed_work() returns 0 in con_work(), con->ops->put() drops
the connection reference held on entry to con_work(). However,
processing is (was) allowed to continue, and at the end of the
function a second con->ops->put() is called.
This patch fixes both problems.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2296,10 +2296,11 @@ restart:
mutex_unlock(&con->mutex);
return;
} else {
- con->ops->put(con);
dout("con_work %p FAILED to back off %lu\n", con,
con->delay);
+ set_bit(CON_FLAG_BACKOFF, &con->flags);
}
+ goto done;
}
if (con->state == CON_STATE_STANDBY) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 9bd952615a42d7e2ce3fa2c632e808e804637a1a)
The ceph_on_in_msg_alloc() method drops con->mutex while it allocates a
message. If that races with a timeout that resends a zillion messages and
resets the connection, and the ->alloc_msg() method returns a NULL message,
it will call ceph_msg_put(NULL) and BUG.
Fix by only calling put if msg is non-NULL.
Fixes http://tracker.newdream.net/issues/3142
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2746,7 +2746,8 @@ static int ceph_con_in_msg_alloc(struct
msg = con->ops->alloc_msg(con, hdr, skip);
mutex_lock(&con->mutex);
if (con->state != CON_STATE_OPEN) {
- ceph_msg_put(msg);
+ if (msg)
+ ceph_msg_put(msg);
return -EAGAIN;
}
con->in_msg = msg;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takamori Yamaguchi <[email protected]>
commit b0a8cc58e6b9aaae3045752059e5e6260c0b94bc upstream.
In kswapd(), set current->reclaim_state to NULL before returning, as
current->reclaim_state holds reference to variable on kswapd()'s stack.
In rare cases, while returning from kswapd() during memory offlining,
__free_slab() and freepages() can access the dangling pointer of
current->reclaim_state.
Signed-off-by: Takamori Yamaguchi <[email protected]>
Signed-off-by: Aaditya Kumar <[email protected]>
Acked-by: David Rientjes <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
mm/vmscan.c | 2 ++
1 file changed, 2 insertions(+)
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3128,6 +3128,8 @@ static int kswapd(void *p)
&balanced_classzone_idx);
}
}
+
+ current->reclaim_state = NULL;
return 0;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ulrich Weber <[email protected]>
commit 38fe36a248ec3228f8e6507955d7ceb0432d2000 upstream.
ICMP tuples have id in src and type/code in dst.
So comparing src.u.all with dst.u.all will always fail here
and ip_xfrm_me_harder() is called for every ICMP packet,
even if there was no NAT.
Signed-off-by: Ulrich Weber <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ipv4/netfilter/nf_nat_standalone.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -194,7 +194,8 @@ nf_nat_out(unsigned int hooknum,
if ((ct->tuplehash[dir].tuple.src.u3.ip !=
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
- (ct->tuplehash[dir].tuple.src.u.all !=
+ (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+ ct->tuplehash[dir].tuple.src.u.all !=
ct->tuplehash[!dir].tuple.dst.u.all)
)
return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP;
@@ -230,7 +231,8 @@ nf_nat_local_fn(unsigned int hooknum,
ret = NF_DROP;
}
#ifdef CONFIG_XFRM
- else if (ct->tuplehash[dir].tuple.dst.u.all !=
+ else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+ ct->tuplehash[dir].tuple.dst.u.all !=
ct->tuplehash[!dir].tuple.src.u.all)
if (ip_xfrm_me_harder(skb))
ret = NF_DROP;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit ee76e0736db8455e3b11827d6899bd2a4e1d0584)
It is simpler to do this immediately, since we already hold the con mutex.
It also avoids the need to deal with a not-quite-CLOSED socket in con_work.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -519,14 +519,8 @@ void ceph_con_close(struct ceph_connecti
reset_connection(con);
con->peer_global_seq = 0;
cancel_delayed_work(&con->work);
+ con_close_socket(con);
mutex_unlock(&con->mutex);
-
- /*
- * We cannot close the socket directly from here because the
- * work threads use it without holding the mutex. Instead, let
- * con_work() do it.
- */
- queue_con(con);
}
EXPORT_SYMBOL(ceph_con_close);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit d63b77f4c552cc3a20506871046ab0fcbc332609)
If we encounter an invalid (e.g., zeroed) mapping, return an error
and avoid a divide by zero.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/osd_client.h | 2 +-
include/linux/ceph/osdmap.h | 6 +++---
net/ceph/osd_client.c | 32 ++++++++++++++++++++------------
net/ceph/osdmap.c | 18 ++++++++++++++++--
4 files changed, 40 insertions(+), 18 deletions(-)
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -207,7 +207,7 @@ extern void ceph_osdc_handle_reply(struc
extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
struct ceph_msg *msg);
-extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
struct ceph_file_layout *layout,
u64 snapid,
u64 off, u64 *plen, u64 *bno,
--- a/include/linux/ceph/osdmap.h
+++ b/include/linux/ceph/osdmap.h
@@ -111,9 +111,9 @@ extern struct ceph_osdmap *osdmap_apply_
extern void ceph_osdmap_destroy(struct ceph_osdmap *map);
/* calculate mapping of a file extent to an object */
-extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
- u64 off, u64 *plen,
- u64 *bno, u64 *oxoff, u64 *oxlen);
+extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+ u64 off, u64 *plen,
+ u64 *bno, u64 *oxoff, u64 *oxlen);
/* calculate mapping of object to a placement group */
extern int ceph_calc_object_layout(struct ceph_object_layout *ol,
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -52,7 +52,7 @@ static int op_has_extent(int op)
op == CEPH_OSD_OP_WRITE);
}
-void ceph_calc_raw_layout(struct ceph_osd_client *osdc,
+int ceph_calc_raw_layout(struct ceph_osd_client *osdc,
struct ceph_file_layout *layout,
u64 snapid,
u64 off, u64 *plen, u64 *bno,
@@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_os
struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
u64 orig_len = *plen;
u64 objoff, objlen; /* extent in object */
+ int r;
reqhead->snapid = cpu_to_le64(snapid);
/* object extent? */
- ceph_calc_file_object_mapping(layout, off, plen, bno,
- &objoff, &objlen);
+ r = ceph_calc_file_object_mapping(layout, off, plen, bno,
+ &objoff, &objlen);
+ if (r < 0)
+ return r;
if (*plen < orig_len)
dout(" skipping last %llu, final file extent %llu~%llu\n",
orig_len - *plen, off, *plen);
@@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_os
dout("calc_layout bno=%llx %llu~%llu (%d pages)\n",
*bno, objoff, objlen, req->r_num_pages);
-
+ return 0;
}
EXPORT_SYMBOL(ceph_calc_raw_layout);
@@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout);
*
* fill osd op in request message.
*/
-static void calc_layout(struct ceph_osd_client *osdc,
- struct ceph_vino vino,
- struct ceph_file_layout *layout,
- u64 off, u64 *plen,
- struct ceph_osd_request *req,
- struct ceph_osd_req_op *op)
+static int calc_layout(struct ceph_osd_client *osdc,
+ struct ceph_vino vino,
+ struct ceph_file_layout *layout,
+ u64 off, u64 *plen,
+ struct ceph_osd_request *req,
+ struct ceph_osd_req_op *op)
{
u64 bno;
+ int r;
- ceph_calc_raw_layout(osdc, layout, vino.snap, off,
- plen, &bno, req, op);
+ r = ceph_calc_raw_layout(osdc, layout, vino.snap, off,
+ plen, &bno, req, op);
+ if (r < 0)
+ return r;
snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno);
req->r_oid_len = strlen(req->r_oid);
+
+ return r;
}
/*
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -952,7 +952,7 @@ bad:
* for now, we write only a single su, until we can
* pass a stride back to the caller.
*/
-void ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
+int ceph_calc_file_object_mapping(struct ceph_file_layout *layout,
u64 off, u64 *plen,
u64 *ono,
u64 *oxoff, u64 *oxlen)
@@ -966,11 +966,17 @@ void ceph_calc_file_object_mapping(struc
dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen,
osize, su);
+ if (su == 0 || sc == 0)
+ goto invalid;
su_per_object = osize / su;
+ if (su_per_object == 0)
+ goto invalid;
dout("osize %u / su %u = su_per_object %u\n", osize, su,
su_per_object);
- BUG_ON((su & ~PAGE_MASK) != 0);
+ if ((su & ~PAGE_MASK) != 0)
+ goto invalid;
+
/* bl = *off / su; */
t = off;
do_div(t, su);
@@ -998,6 +1004,14 @@ void ceph_calc_file_object_mapping(struc
*plen = *oxlen;
dout(" obj extent %llu~%llu\n", *oxoff, *oxlen);
+ return 0;
+
+invalid:
+ dout(" invalid layout\n");
+ *ono = 0;
+ *oxoff = 0;
+ *oxlen = 0;
+ return -EINVAL;
}
EXPORT_SYMBOL(ceph_calc_file_object_mapping);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e27947c767f5bed15048f4e4dad3e2eb69133697)
There is no state explicitly defined when a ceph connection is fully
operational. So define one.
It's set when the connection sequence completes successfully, and is
cleared when the connection gets closed.
Be a little more careful when examining the old state when a socket
disconnect event is reported.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 1 +
net/ceph/messenger.c | 9 +++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -120,6 +120,7 @@ struct ceph_msg_pos {
*/
#define CONNECTING 1
#define NEGOTIATING 2
+#define CONNECTED 5
#define STANDBY 8 /* no outgoing messages, socket closed. we keep
* the ceph_connection around to maintain shared
* state with the peer. */
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -463,6 +463,7 @@ void ceph_con_close(struct ceph_connecti
ceph_pr_addr(&con->peer_addr.in_addr));
clear_bit(NEGOTIATING, &con->state);
clear_bit(CONNECTING, &con->state);
+ clear_bit(CONNECTED, &con->state);
clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */
set_bit(CLOSED, &con->state);
@@ -1564,6 +1565,7 @@ static int process_connect(struct ceph_c
}
clear_bit(NEGOTIATING, &con->state);
clear_bit(CONNECTING, &con->state);
+ set_bit(CONNECTED, &con->state);
con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
con->connect_seq++;
con->peer_features = server_feat;
@@ -2114,6 +2116,7 @@ more:
prepare_read_ack(con);
break;
case CEPH_MSGR_TAG_CLOSE:
+ clear_bit(CONNECTED, &con->state);
set_bit(CLOSED, &con->state); /* fixme */
goto out;
default:
@@ -2190,11 +2193,13 @@ static void con_work(struct work_struct
mutex_lock(&con->mutex);
restart:
if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
- if (test_and_clear_bit(CONNECTING, &con->state)) {
+ if (test_and_clear_bit(CONNECTED, &con->state))
+ con->error_msg = "socket closed";
+ else if (test_and_clear_bit(CONNECTING, &con->state)) {
clear_bit(NEGOTIATING, &con->state);
con->error_msg = "connection failed";
} else {
- con->error_msg = "socket closed";
+ con->error_msg = "unrecognized con state";
}
goto fault;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Chinner <[email protected]>
commit d69043c42d8c6414fa28ad18d99973aa6c1c2e24 upstream.
Error handling in xfs_buf_ioapply_map() does not handle IO reference
counts correctly. We increment the b_io_remaining count before
building the bio, but then fail to decrement it in the failure case.
This leads to the buffer never running IO completion and releasing
the reference that the IO holds, so at unmount we can leak the
buffer. This leak is captured by this assert failure during unmount:
XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/xfs_mount.c, line: 273
This is not a new bug - the b_io_remaining accounting has had this
problem for a long, long time - it's just very hard to get a
zero length bio being built by this code...
Further, the buffer IO error can be overwritten on a multi-segment
buffer by subsequent bio completions for partial sections of the
buffer. Hence we should only set the buffer error status if the
buffer is not already carrying an error status. This ensures that a
partial IO error on a multi-segment buffer will not be lost. This
part of the problem is a regression, however.
Signed-off-by: Dave Chinner <[email protected]>
Reviewed-by: Mark Tinguely <[email protected]>
Signed-off-by: Ben Myers <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/xfs/xfs_buf.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1165,9 +1165,14 @@ xfs_buf_bio_end_io(
{
xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private;
- xfs_buf_ioerror(bp, -error);
+ /*
+ * don't overwrite existing errors - otherwise we can lose errors on
+ * buffers that require multiple bios to complete.
+ */
+ if (!bp->b_error)
+ xfs_buf_ioerror(bp, -error);
- if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+ if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
_xfs_buf_ioend(bp, 1);
@@ -1243,6 +1248,11 @@ next_chunk:
if (size)
goto next_chunk;
} else {
+ /*
+ * This is guaranteed not to be the last io reference count
+ * because the caller (xfs_buf_iorequest) holds a count itself.
+ */
+ atomic_dec(&bp->b_io_remaining);
xfs_buf_ioerror(bp, EIO);
bio_put(bio);
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit a8d00e3cdef4c1c4f194414b72b24cd995439a05)
The following commit changed it so SOCK_CLOSED bit was stored in
a connection's new "flags" field rather than its "state" field.
libceph: start separating connection flags from state
commit 928443cd
That bit is used in con_close_socket() to protect against setting an
error message more than once in the socket event handler function.
Unfortunately, the field being operated on in that function was not
updated to be "flags" as it should have been. This fixes that
error.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -397,11 +397,11 @@ static int con_close_socket(struct ceph_
dout("con_close_socket on %p sock %p\n", con, con->sock);
if (!con->sock)
return 0;
- set_bit(SOCK_CLOSED, &con->state);
+ set_bit(SOCK_CLOSED, &con->flags);
rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
sock_release(con->sock);
con->sock = NULL;
- clear_bit(SOCK_CLOSED, &con->state);
+ clear_bit(SOCK_CLOSED, &con->flags);
con_sock_state_closed(con);
return rc;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 57dac9d1620942608306d8c17c98a9d1568ffdf4)
There are two blocks of code in read_partial_message()--those that
read the header and footer of the message--that can be replaced by a
call to read_partial(). Do that.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1628,7 +1628,7 @@ static int read_partial_message(struct c
{
struct ceph_msg *m = con->in_msg;
int ret;
- int to, left;
+ int to;
unsigned front_len, middle_len, data_len;
bool do_datacrc = !con->msgr->nocrc;
int skip;
@@ -1638,15 +1638,10 @@ static int read_partial_message(struct c
dout("read_partial_message con %p msg %p\n", con, m);
/* header */
- while (con->in_base_pos < sizeof(con->in_hdr)) {
- left = sizeof(con->in_hdr) - con->in_base_pos;
- ret = ceph_tcp_recvmsg(con->sock,
- (char *)&con->in_hdr + con->in_base_pos,
- left);
- if (ret <= 0)
- return ret;
- con->in_base_pos += ret;
- }
+ to = 0;
+ ret = read_partial(con, &to, sizeof (con->in_hdr), &con->in_hdr);
+ if (ret <= 0)
+ return ret;
crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc));
if (cpu_to_le32(crc) != con->in_hdr.crc) {
@@ -1759,16 +1754,11 @@ static int read_partial_message(struct c
}
/* footer */
- to = sizeof(m->hdr) + sizeof(m->footer);
- while (con->in_base_pos < to) {
- left = to - con->in_base_pos;
- ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer +
- (con->in_base_pos - sizeof(m->hdr)),
- left);
- if (ret <= 0)
- return ret;
- con->in_base_pos += ret;
- }
+ to = sizeof (m->hdr);
+ ret = read_partial(con, &to, sizeof (m->footer), &m->footer);
+ if (ret <= 0)
+ return ret;
+
dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n",
m, front_len, m->footer.front_crc, middle_len,
m->footer.middle_crc, data_len, m->footer.data_crc);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Williams <[email protected]>
commit c0bc3098871dd9b964f6b45ec1e4d70d87811744 upstream.
Signed-off-by: Dan Williams <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/usb/serial/option.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -286,6 +286,7 @@ static void option_instat_callback(struc
/* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S_X200 0x0000
+#define ALCATEL_PRODUCT_X220_X500D 0x0017
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -1163,6 +1164,7 @@ static const struct usb_device_id option
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
.driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
},
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit e10006f807ffc4d5b1d861305d18d9e8145891ca)
Pass the osd number to the create_osd() routine, and move the
initialization of fields that depend on it therein.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/osd_client.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -624,7 +624,7 @@ static void osd_reset(struct ceph_connec
/*
* Track open sessions with osds.
*/
-static struct ceph_osd *create_osd(struct ceph_osd_client *osdc)
+static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
{
struct ceph_osd *osd;
@@ -634,6 +634,7 @@ static struct ceph_osd *create_osd(struc
atomic_set(&osd->o_ref, 1);
osd->o_osdc = osdc;
+ osd->o_osd = onum;
INIT_LIST_HEAD(&osd->o_requests);
INIT_LIST_HEAD(&osd->o_linger_requests);
INIT_LIST_HEAD(&osd->o_osd_lru);
@@ -643,6 +644,7 @@ static struct ceph_osd *create_osd(struc
osd->o_con.private = osd;
osd->o_con.ops = &osd_con_ops;
osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
+ osd->o_con.peer_name.num = cpu_to_le64(onum);
INIT_LIST_HEAD(&osd->o_keepalive_item);
return osd;
@@ -998,15 +1000,13 @@ static int __map_request(struct ceph_osd
req->r_osd = __lookup_osd(osdc, o);
if (!req->r_osd && o >= 0) {
err = -ENOMEM;
- req->r_osd = create_osd(osdc);
+ req->r_osd = create_osd(osdc, o);
if (!req->r_osd) {
list_move(&req->r_req_lru_item, &osdc->req_notarget);
goto out;
}
dout("map_request osd %p is osd%d\n", req->r_osd, o);
- req->r_osd->o_osd = o;
- req->r_osd->o_con.peer_name.num = cpu_to_le64(o);
__insert_osd(osdc, req->r_osd);
ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Durgin <[email protected]>
(cherry picked from commit 403f24d3d51760a8b9368d595fa5f48c309f1a0f)
This is updated whenever a snapshot is added or deleted, and the
snapc pointer is changed with every refresh of the header.
Signed-off-by: Josh Durgin <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/block/rbd.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1683,7 +1683,9 @@ static int rbd_header_add_snap(struct rb
if (ret < 0)
return ret;
- dev->header.snapc->seq = new_snapid;
+ down_write(&dev->header_rwsem);
+ dev->header.snapc->seq = new_snapid;
+ up_write(&dev->header_rwsem);
return 0;
bad:
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 4740a623d20c51d167da7f752b63e2b8714b2543)
This function's calling convention is very limiting. In particular,
we can't return any error other than ENOMEM (and only implicitly),
which is a problem (see next patch).
Instead, return an normal 0 or error code, and make the skip a pointer
output parameter. Drop the useless in_hdr argument (we have the con
pointer).
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 56 ++++++++++++++++++++++++++++-----------------------
1 file changed, 31 insertions(+), 25 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1733,9 +1733,7 @@ static int read_partial_message_section(
return 1;
}
-static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
- struct ceph_msg_header *hdr);
-
+static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip);
static int read_partial_message_pages(struct ceph_connection *con,
struct page **pages,
@@ -1864,9 +1862,14 @@ static int read_partial_message(struct c
/* allocate message? */
if (!con->in_msg) {
+ int skip = 0;
+
dout("got hdr type %d front %d data %d\n", con->in_hdr.type,
con->in_hdr.front_len, con->in_hdr.data_len);
- if (ceph_con_in_msg_alloc(con, &con->in_hdr)) {
+ ret = ceph_con_in_msg_alloc(con, &skip);
+ if (ret < 0)
+ return ret;
+ if (skip) {
/* skip this message */
dout("alloc_msg said skip message\n");
BUG_ON(con->in_msg);
@@ -1876,12 +1879,8 @@ static int read_partial_message(struct c
con->in_seq++;
return 0;
}
- if (!con->in_msg) {
- con->error_msg =
- "error allocating memory for incoming message";
- return -ENOMEM;
- }
+ BUG_ON(!con->in_msg);
BUG_ON(con->in_msg->con != con);
m = con->in_msg;
m->front.iov_len = 0; /* haven't read it yet */
@@ -2715,43 +2714,50 @@ static int ceph_alloc_middle(struct ceph
* connection, and save the result in con->in_msg. Uses the
* connection's private alloc_msg op if available.
*
- * Returns true if the message should be skipped, false otherwise.
- * If true is returned (skip message), con->in_msg will be NULL.
- * If false is returned, con->in_msg will contain a pointer to the
- * newly-allocated message, or NULL in case of memory exhaustion.
+ * Returns 0 on success, or a negative error code.
+ *
+ * On success, if we set *skip = 1:
+ * - the next message should be skipped and ignored.
+ * - con->in_msg == NULL
+ * or if we set *skip = 0:
+ * - con->in_msg is non-null.
+ * On error (ENOMEM, EAGAIN, ...),
+ * - con->in_msg == NULL
*/
-static bool ceph_con_in_msg_alloc(struct ceph_connection *con,
- struct ceph_msg_header *hdr)
+static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
{
+ struct ceph_msg_header *hdr = &con->in_hdr;
int type = le16_to_cpu(hdr->type);
int front_len = le32_to_cpu(hdr->front_len);
int middle_len = le32_to_cpu(hdr->middle_len);
- int ret;
+ int ret = 0;
BUG_ON(con->in_msg != NULL);
if (con->ops->alloc_msg) {
- int skip = 0;
-
mutex_unlock(&con->mutex);
- con->in_msg = con->ops->alloc_msg(con, hdr, &skip);
+ con->in_msg = con->ops->alloc_msg(con, hdr, skip);
mutex_lock(&con->mutex);
if (con->in_msg) {
con->in_msg->con = con->ops->get(con);
BUG_ON(con->in_msg->con == NULL);
}
- if (skip)
+ if (*skip) {
con->in_msg = NULL;
-
- if (!con->in_msg)
- return skip != 0;
+ return 0;
+ }
+ if (!con->in_msg) {
+ con->error_msg =
+ "error allocating memory for incoming message";
+ return -ENOMEM;
+ }
}
if (!con->in_msg) {
con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false);
if (!con->in_msg) {
pr_err("unable to allocate msg type %d len %d\n",
type, front_len);
- return false;
+ return -ENOMEM;
}
con->in_msg->con = con->ops->get(con);
BUG_ON(con->in_msg->con == NULL);
@@ -2767,7 +2773,7 @@ static bool ceph_con_in_msg_alloc(struct
}
}
- return false;
+ return ret;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 5469155f2bc83bb2c88b0a0370c3d54d87eed06e)
Take the con mutex while we are initiating a ceph open. This is necessary
because the may have previously been in use and then closed, which could
result in a racing workqueue running con_work().
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Yehuda Sadeh <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -537,6 +537,7 @@ void ceph_con_open(struct ceph_connectio
__u8 entity_type, __u64 entity_num,
struct ceph_entity_addr *addr)
{
+ mutex_lock(&con->mutex);
dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
set_bit(OPENING, &con->state);
WARN_ON(!test_and_clear_bit(CLOSED, &con->state));
@@ -546,6 +547,7 @@ void ceph_con_open(struct ceph_connectio
memcpy(&con->peer_addr, addr, sizeof(*addr));
con->delay = 0; /* reset backoff memory */
+ mutex_unlock(&con->mutex);
queue_con(con);
}
EXPORT_SYMBOL(ceph_con_open);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
commit 361d94a338a3fd0cee6a4ea32bbc427ba228e628 upstream.
Calls into reiserfs journalling code and reiserfs_get_block() need to
be protected with write lock. We remove write lock around calls to high
level quota code in the next patch so these paths would suddently become
unprotected.
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/reiserfs/super.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2303,7 +2303,9 @@ static ssize_t reiserfs_quota_write(stru
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
tmp_bh.b_state = 0;
+ reiserfs_write_lock(sb);
err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+ reiserfs_write_unlock(sb);
if (err)
goto out;
if (offset || tocopy != sb->s_blocksize)
@@ -2319,10 +2321,12 @@ static ssize_t reiserfs_quota_write(stru
flush_dcache_page(bh->b_page);
set_buffer_uptodate(bh);
unlock_buffer(bh);
+ reiserfs_write_lock(sb);
reiserfs_prepare_for_journal(sb, bh, 1);
journal_mark_dirty(current->journal_info, sb, bh);
if (!journal_quota)
reiserfs_add_ordered_list(inode, bh);
+ reiserfs_write_unlock(sb);
brelse(bh);
offset = 0;
towrite -= tocopy;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tom Herbert <[email protected]>
[ Upstream commit baefa31db2f2b13a05d1b81bdf2d20d487f58b0a ]
In commit c445477d74ab3779 which adds aRFS to the kernel, the CPU
selected for RFS is not set correctly when CPU is changing.
This is causing OOO packets and probably other issues.
Signed-off-by: Tom Herbert <[email protected]>
Acked-by: Eric Dumazet <[email protected]>
Acked-by: Ben Hutchings <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/core/dev.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2763,8 +2763,10 @@ static int get_rps_cpu(struct net_device
if (unlikely(tcpu != next_cpu) &&
(tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
((int)(per_cpu(softnet_data, tcpu).input_queue_head -
- rflow->last_qtail)) >= 0))
+ rflow->last_qtail)) >= 0)) {
+ tcpu = next_cpu;
rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+ }
if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
*rflowp = rflow;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 5a0f8fdd8a0ebe320952a388331dc043d7e14ced)
prepare_write_connect() can return an error, but only one of its
callers checks for it. All the rest are in functions that already
return errors, so it should be fine to return the error if one
gets returned.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1409,7 +1409,9 @@ static int process_connect(struct ceph_c
ceph_pr_addr(&con->peer_addr.in_addr));
reset_connection(con);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+ return ret;
prepare_read_connect(con);
/* Tell ceph about it. */
@@ -1433,7 +1435,9 @@ static int process_connect(struct ceph_c
le32_to_cpu(con->in_connect.connect_seq));
con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+ return ret;
prepare_read_connect(con);
break;
@@ -1448,7 +1452,9 @@ static int process_connect(struct ceph_c
get_global_seq(con->msgr,
le32_to_cpu(con->in_connect.global_seq));
ceph_con_out_kvec_reset(con);
- prepare_write_connect(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+ return ret;
prepare_read_connect(con);
break;
@@ -1854,7 +1860,9 @@ more:
if (con->sock == NULL) {
ceph_con_out_kvec_reset(con);
prepare_write_banner(con);
- prepare_write_connect(con);
+ ret = prepare_write_connect(con);
+ if (ret < 0)
+ goto out;
prepare_read_banner(con);
set_bit(CONNECTING, &con->state);
clear_bit(NEGOTIATING, &con->state);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 7593af920baac37752190a0db703d2732bed4a3b)
Currently a ceph connection enters a "CONNECTING" state when it
begins the process of (re-)connecting with its peer. Once the two
ends have successfully exchanged their banner and addresses, an
additional NEGOTIATING bit is set in the ceph connection's state to
indicate the connection information exhange has begun. The
CONNECTING bit/state continues to be set during this phase.
Rather than have the CONNECTING state continue while the NEGOTIATING
bit is set, interpret these two phases as distinct states. In other
words, when NEGOTIATING is set, clear CONNECTING. That way only
one of them will be active at a time.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 50 +++++++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 23 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1559,7 +1559,6 @@ static int process_connect(struct ceph_c
return -1;
}
clear_bit(NEGOTIATING, &con->state);
- clear_bit(CONNECTING, &con->state);
set_bit(CONNECTED, &con->state);
con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq);
con->connect_seq++;
@@ -2000,7 +1999,8 @@ more_kvec:
}
do_next:
- if (!test_bit(CONNECTING, &con->state)) {
+ if (!test_bit(CONNECTING, &con->state) &&
+ !test_bit(NEGOTIATING, &con->state)) {
/* is anything else pending? */
if (!list_empty(&con->out_queue)) {
prepare_write_message(con);
@@ -2057,25 +2057,29 @@ more:
}
if (test_bit(CONNECTING, &con->state)) {
- if (!test_bit(NEGOTIATING, &con->state)) {
- dout("try_read connecting\n");
- ret = read_partial_banner(con);
- if (ret <= 0)
- goto out;
- ret = process_banner(con);
- if (ret < 0)
- goto out;
-
- /* Banner is good, exchange connection info */
- ret = prepare_write_connect(con);
- if (ret < 0)
- goto out;
- prepare_read_connect(con);
- set_bit(NEGOTIATING, &con->state);
+ dout("try_read connecting\n");
+ ret = read_partial_banner(con);
+ if (ret <= 0)
+ goto out;
+ ret = process_banner(con);
+ if (ret < 0)
+ goto out;
+
+ clear_bit(CONNECTING, &con->state);
+ set_bit(NEGOTIATING, &con->state);
- /* Send connection info before awaiting response */
+ /* Banner is good, exchange connection info */
+ ret = prepare_write_connect(con);
+ if (ret < 0)
goto out;
- }
+ prepare_read_connect(con);
+
+ /* Send connection info before awaiting response */
+ goto out;
+ }
+
+ if (test_bit(NEGOTIATING, &con->state)) {
+ dout("try_read negotiating\n");
ret = read_partial_connect(con);
if (ret <= 0)
goto out;
@@ -2197,12 +2201,12 @@ restart:
if (test_and_clear_bit(SOCK_CLOSED, &con->flags)) {
if (test_and_clear_bit(CONNECTED, &con->state))
con->error_msg = "socket closed";
- else if (test_and_clear_bit(CONNECTING, &con->state)) {
- clear_bit(NEGOTIATING, &con->state);
+ else if (test_and_clear_bit(NEGOTIATING, &con->state))
+ con->error_msg = "negotiation failed";
+ else if (test_and_clear_bit(CONNECTING, &con->state))
con->error_msg = "connection failed";
- } else {
+ else
con->error_msg = "unrecognized con state";
- }
goto fault;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanjun He <[email protected]>
(cherry picked from commit a2a3258417eb6a1799cf893350771428875a8287)
Add an atomic variable 'stopping' as flag in struct ceph_messenger,
set this flag to 1 in function ceph_destroy_client(), and add the condition code
in function ceph_data_ready() to test the flag value, if true(1), just return.
Signed-off-by: Guanjun He <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 1 +
net/ceph/ceph_common.c | 2 ++
net/ceph/messenger.c | 5 +++++
3 files changed, 8 insertions(+)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -50,6 +50,7 @@ struct ceph_messenger {
struct ceph_entity_inst inst; /* my name+address */
struct ceph_entity_addr my_enc_addr;
+ atomic_t stopping;
bool nocrc;
/*
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -495,6 +495,8 @@ void ceph_destroy_client(struct ceph_cli
{
dout("destroy_client %p\n", client);
+ atomic_set(&client->msgr.stopping, 1);
+
/* unmount */
ceph_osdc_stop(&client->osdc);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -254,6 +254,9 @@ static void con_sock_state_closed(struct
static void ceph_sock_data_ready(struct sock *sk, int count_unused)
{
struct ceph_connection *con = sk->sk_user_data;
+ if (atomic_read(&con->msgr->stopping)) {
+ return;
+ }
if (sk->sk_state != TCP_CLOSE_WAIT) {
dout("%s on %p state = %lu, queueing work\n", __func__,
@@ -2413,6 +2416,8 @@ void ceph_messenger_init(struct ceph_mes
encode_my_addr(msgr);
msgr->nocrc = nocrc;
+ atomic_set(&msgr->stopping, 0);
+
dout("%s %p\n", __func__, msgr);
}
EXPORT_SYMBOL(ceph_messenger_init);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 5ce765a540f34d1e2005e1210f49f67fdf11e997)
In write_partial_msg_pages(), pages need to be kmapped in order to
perform a CRC-32c calculation on them. As an artifact of the way
this code used to be structured, the kunmap() call was separated
from the kmap() call and both were done conditionally. But the
conditions under which the kmap() and kunmap() calls were made
differed, so there was a chance a kunmap() call would be done on a
page that had not been mapped.
The symptom of this was tripping a BUG() in kunmap_high() when
pkmap_count[nr] became 0.
Reported-by: Bryan K. Wright <[email protected]>
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1069,16 +1069,13 @@ static int write_partial_msg_pages(struc
BUG_ON(kaddr == NULL);
base = kaddr + con->out_msg_pos.page_pos + bio_offset;
crc = crc32c(crc, base, len);
+ kunmap(page);
msg->footer.data_crc = cpu_to_le32(crc);
con->out_msg_pos.did_page_crc = true;
}
ret = ceph_tcp_sendpage(con->sock, page,
con->out_msg_pos.page_pos + bio_offset,
len, 1);
-
- if (do_datacrc)
- kunmap(page);
-
if (ret <= 0)
goto out;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit b1c6b9803f5491e94041e6da96bc9dec3870e792)
Change prepare_connect_authorizer() so it returns without dropping
the connection mutex if the connection has no get_authorizer method.
Use the symbolic CEPH_AUTH_UNKNOWN instead of 0 when assigning
authorization protocols.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -656,19 +656,29 @@ static void prepare_write_keepalive(stru
static int prepare_connect_authorizer(struct ceph_connection *con)
{
void *auth_buf;
- int auth_len = 0;
- int auth_protocol = 0;
+ int auth_len;
+ int auth_protocol;
+
+ if (!con->ops->get_authorizer) {
+ con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
+ con->out_connect.authorizer_len = 0;
+
+ return 0;
+ }
+
+ /* Can't hold the mutex while getting authorizer */
mutex_unlock(&con->mutex);
- if (con->ops->get_authorizer)
- con->ops->get_authorizer(con, &auth_buf, &auth_len,
- &auth_protocol, &con->auth_reply_buf,
- &con->auth_reply_buf_len,
- con->auth_retry);
+
+ auth_buf = NULL;
+ auth_len = 0;
+ auth_protocol = CEPH_AUTH_UNKNOWN;
+ con->ops->get_authorizer(con, &auth_buf, &auth_len, &auth_protocol,
+ &con->auth_reply_buf, &con->auth_reply_buf_len,
+ con->auth_retry);
mutex_lock(&con->mutex);
- if (test_bit(CLOSED, &con->state) ||
- test_bit(OPENING, &con->state))
+ if (test_bit(CLOSED, &con->state) || test_bit(OPENING, &con->state))
return -EAGAIN;
con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 74f1869f76d043bad12ec03b4d5f04a8c3d1f157)
Make use of the new ceph_auth_handshake structure in order to reduce
the number of arguments passed to the create_authorizor method in
ceph_auth_client_ops. Use a local variable of that type as a
shorthand in the get_authorizer method definitions.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 27 ++++++++++++---------------
include/linux/ceph/auth.h | 4 +---
net/ceph/auth_none.c | 15 +++++++--------
net/ceph/auth_x.c | 15 +++++++--------
net/ceph/osd_client.c | 26 +++++++++++---------------
5 files changed, 38 insertions(+), 49 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -3402,31 +3402,28 @@ static int get_authorizer(struct ceph_co
struct ceph_mds_session *s = con->private;
struct ceph_mds_client *mdsc = s->s_mdsc;
struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
+ struct ceph_auth_handshake *auth = &s->s_auth;
int ret = 0;
- if (force_new && s->s_auth.authorizer) {
- ac->ops->destroy_authorizer(ac, s->s_auth.authorizer);
- s->s_auth.authorizer = NULL;
+ if (force_new && auth->authorizer) {
+ ac->ops->destroy_authorizer(ac, auth->authorizer);
+ auth->authorizer = NULL;
}
- if (s->s_auth.authorizer == NULL) {
+ if (auth->authorizer == NULL) {
if (ac->ops->create_authorizer) {
- ret = ac->ops->create_authorizer(
- ac, CEPH_ENTITY_TYPE_MDS,
- &s->s_auth.authorizer,
- &s->s_auth.authorizer_buf,
- &s->s_auth.authorizer_buf_len,
- &s->s_auth.authorizer_reply_buf,
- &s->s_auth.authorizer_reply_buf_len);
+ ret = ac->ops->create_authorizer(ac,
+ CEPH_ENTITY_TYPE_MDS, auth);
if (ret)
return ret;
}
}
*proto = ac->protocol;
- *buf = s->s_auth.authorizer_buf;
- *len = s->s_auth.authorizer_buf_len;
- *reply_buf = s->s_auth.authorizer_reply_buf;
- *reply_len = s->s_auth.authorizer_reply_buf_len;
+ *buf = auth->authorizer_buf;
+ *len = auth->authorizer_buf_len;
+ *reply_buf = auth->authorizer_reply_buf;
+ *reply_len = auth->authorizer_reply_buf_len;
+
return 0;
}
--- a/include/linux/ceph/auth.h
+++ b/include/linux/ceph/auth.h
@@ -51,9 +51,7 @@ struct ceph_auth_client_ops {
* the response to authenticate the service.
*/
int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
- struct ceph_authorizer **a,
- void **buf, size_t *len,
- void **reply_buf, size_t *reply_len);
+ struct ceph_auth_handshake *auth);
int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
struct ceph_authorizer *a, size_t len);
void (*destroy_authorizer)(struct ceph_auth_client *ac,
--- a/net/ceph/auth_none.c
+++ b/net/ceph/auth_none.c
@@ -59,9 +59,7 @@ static int handle_reply(struct ceph_auth
*/
static int ceph_auth_none_create_authorizer(
struct ceph_auth_client *ac, int peer_type,
- struct ceph_authorizer **a,
- void **buf, size_t *len,
- void **reply_buf, size_t *reply_len)
+ struct ceph_auth_handshake *auth)
{
struct ceph_auth_none_info *ai = ac->private;
struct ceph_none_authorizer *au = &ai->au;
@@ -82,11 +80,12 @@ static int ceph_auth_none_create_authori
dout("built authorizer len %d\n", au->buf_len);
}
- *a = (struct ceph_authorizer *)au;
- *buf = au->buf;
- *len = au->buf_len;
- *reply_buf = au->reply_buf;
- *reply_len = sizeof(au->reply_buf);
+ auth->authorizer = (struct ceph_authorizer *) au;
+ auth->authorizer_buf = au->buf;
+ auth->authorizer_buf_len = au->buf_len;
+ auth->authorizer_reply_buf = au->reply_buf;
+ auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
+
return 0;
bad2:
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -526,9 +526,7 @@ static int ceph_x_handle_reply(struct ce
static int ceph_x_create_authorizer(
struct ceph_auth_client *ac, int peer_type,
- struct ceph_authorizer **a,
- void **buf, size_t *len,
- void **reply_buf, size_t *reply_len)
+ struct ceph_auth_handshake *auth)
{
struct ceph_x_authorizer *au;
struct ceph_x_ticket_handler *th;
@@ -548,11 +546,12 @@ static int ceph_x_create_authorizer(
return ret;
}
- *a = (struct ceph_authorizer *)au;
- *buf = au->buf->vec.iov_base;
- *len = au->buf->vec.iov_len;
- *reply_buf = au->reply_buf;
- *reply_len = sizeof(au->reply_buf);
+ auth->authorizer = (struct ceph_authorizer *) au;
+ auth->authorizer_buf = au->buf->vec.iov_base;
+ auth->authorizer_buf_len = au->buf->vec.iov_len;
+ auth->authorizer_reply_buf = au->reply_buf;
+ auth->authorizer_reply_buf_len = sizeof (au->reply_buf);
+
return 0;
}
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2115,29 +2115,25 @@ static int get_authorizer(struct ceph_co
struct ceph_osd *o = con->private;
struct ceph_osd_client *osdc = o->o_osdc;
struct ceph_auth_client *ac = osdc->client->monc.auth;
+ struct ceph_auth_handshake *auth = &o->o_auth;
int ret = 0;
- if (force_new && o->o_auth.authorizer) {
- ac->ops->destroy_authorizer(ac, o->o_auth.authorizer);
- o->o_auth.authorizer = NULL;
+ if (force_new && auth->authorizer) {
+ ac->ops->destroy_authorizer(ac, auth->authorizer);
+ auth->authorizer = NULL;
}
- if (o->o_auth.authorizer == NULL) {
- ret = ac->ops->create_authorizer(
- ac, CEPH_ENTITY_TYPE_OSD,
- &o->o_auth.authorizer,
- &o->o_auth.authorizer_buf,
- &o->o_auth.authorizer_buf_len,
- &o->o_auth.authorizer_reply_buf,
- &o->o_auth.authorizer_reply_buf_len);
+ if (auth->authorizer == NULL) {
+ ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth);
if (ret)
return ret;
}
*proto = ac->protocol;
- *buf = o->o_auth.authorizer_buf;
- *len = o->o_auth.authorizer_buf_len;
- *reply_buf = o->o_auth.authorizer_reply_buf;
- *reply_len = o->o_auth.authorizer_reply_buf_len;
+ *buf = auth->authorizer_buf;
+ *len = auth->authorizer_buf_len;
+ *reply_buf = auth->authorizer_reply_buf;
+ *reply_len = auth->authorizer_reply_buf_len;
+
return 0;
}
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Schwidefsky <[email protected]>
commit fa968ee215c0ca91e4a9c3a69ac2405aae6e5d2f upstream.
If user space is running in primary mode it can switch to secondary
or access register mode, this is used e.g. in the clock_gettime code
of the vdso. If a signal is delivered to the user space process while
it has been running in access register mode the signal handler is
executed in access register mode as well which will result in a crash
most of the time.
Set the address space control bits in the PSW to the default for the
execution of the signal handler and make sure that the previous
address space control is restored on signal return. Take care
that user space can not switch to the kernel address space by
modifying the registers in the signal frame.
Signed-off-by: Martin Schwidefsky <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/s390/include/asm/compat.h | 2 +-
arch/s390/include/asm/ptrace.h | 4 ++--
arch/s390/kernel/compat_signal.c | 14 ++++++++++++--
arch/s390/kernel/signal.c | 14 ++++++++++++--
4 files changed, 27 insertions(+), 7 deletions(-)
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -20,7 +20,7 @@
#define PSW32_MASK_CC 0x00003000UL
#define PSW32_MASK_PM 0x00000f00UL
-#define PSW32_MASK_USER 0x00003F00UL
+#define PSW32_MASK_USER 0x0000FF00UL
#define PSW32_ADDR_AMODE 0x80000000UL
#define PSW32_ADDR_INSN 0x7FFFFFFFUL
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -240,7 +240,7 @@ typedef struct
#define PSW_MASK_EA 0x00000000UL
#define PSW_MASK_BA 0x00000000UL
-#define PSW_MASK_USER 0x00003F00UL
+#define PSW_MASK_USER 0x0000FF00UL
#define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL
@@ -269,7 +269,7 @@ typedef struct
#define PSW_MASK_EA 0x0000000100000000UL
#define PSW_MASK_BA 0x0000000080000000UL
-#define PSW_MASK_USER 0x00003F0180000000UL
+#define PSW_MASK_USER 0x0000FF0180000000UL
#define PSW_ADDR_AMODE 0x0000000000000000UL
#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -313,6 +313,10 @@ static int restore_sigregs32(struct pt_r
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+ /* Check for invalid user address space control. */
+ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -494,7 +498,10 @@ static int setup_frame32(int sig, struct
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
+ /* Force 31 bit amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__force __u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
@@ -562,7 +569,10 @@ static int setup_rt_frame32(int sig, str
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
+ /* Force 31 bit amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -148,6 +148,10 @@ static int restore_sigregs(struct pt_reg
/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(user_sregs.regs.psw.mask & PSW_MASK_USER);
+ /* Check for invalid user address space control. */
+ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
/* Check for invalid amode */
if (regs->psw.mask & PSW_MASK_EA)
regs->psw.mask |= PSW_MASK_BA;
@@ -294,7 +298,10 @@ static int setup_frame(int sig, struct k
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
+ /* Force default amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
@@ -367,7 +374,10 @@ static int setup_rt_frame(int sig, struc
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
+ /* Force default amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Yan, Zheng" <[email protected]>
(cherry picked from commit 3e8f43a089f06279c5f76a9ccd42578eebf7bfa5)
When i >= newmap->m_max_mds, ceph_mdsmap_get_addr(newmap, i) return
NULL. Passing NULL to memcmp() triggers oops.
Signed-off-by: Yan, Zheng <[email protected]>
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2634,7 +2634,8 @@ static void check_new_map(struct ceph_md
ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
session_state_name(s->s_state));
- if (memcmp(ceph_mdsmap_get_addr(oldmap, i),
+ if (i >= newmap->m_max_mds ||
+ memcmp(ceph_mdsmap_get_addr(oldmap, i),
ceph_mdsmap_get_addr(newmap, i),
sizeof(struct ceph_entity_addr))) {
if (s->s_state == CEPH_MDS_SESSION_OPENING) {
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit 1bfd89f4e6e1adc6a782d94aa5d4c53be1e404d7)
Move the initialization of a ceph connection's private pointer,
operations vector pointer, and peer name information into
ceph_con_init(). Rearrange the arguments so the connection pointer
is first. Hide the byte-swapping of the peer entity number inside
ceph_con_init()
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
fs/ceph/mds_client.c | 7 ++-----
include/linux/ceph/messenger.h | 6 ++++--
net/ceph/messenger.c | 9 ++++++++-
net/ceph/mon_client.c | 8 +++-----
net/ceph/osd_client.c | 7 ++-----
5 files changed, 19 insertions(+), 18 deletions(-)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -394,11 +394,8 @@ static struct ceph_mds_session *register
s->s_seq = 0;
mutex_init(&s->s_mutex);
- ceph_con_init(&mdsc->fsc->client->msgr, &s->s_con);
- s->s_con.private = s;
- s->s_con.ops = &mds_con_ops;
- s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
- s->s_con.peer_name.num = cpu_to_le64(mds);
+ ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr,
+ CEPH_ENTITY_TYPE_MDS, mds);
spin_lock_init(&s->s_gen_ttl_lock);
s->s_cap_gen = 0;
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -219,8 +219,10 @@ extern void ceph_messenger_init(struct c
u32 required_features,
bool nocrc);
-extern void ceph_con_init(struct ceph_messenger *msgr,
- struct ceph_connection *con);
+extern void ceph_con_init(struct ceph_connection *con, void *private,
+ const struct ceph_connection_operations *ops,
+ struct ceph_messenger *msgr, __u8 entity_type,
+ __u64 entity_num);
extern void ceph_con_open(struct ceph_connection *con,
struct ceph_entity_addr *addr);
extern bool ceph_con_opened(struct ceph_connection *con);
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -521,15 +521,22 @@ void ceph_con_put(struct ceph_connection
/*
* initialize a new connection.
*/
-void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con)
+void ceph_con_init(struct ceph_connection *con, void *private,
+ const struct ceph_connection_operations *ops,
+ struct ceph_messenger *msgr, __u8 entity_type, __u64 entity_num)
{
dout("con_init %p\n", con);
memset(con, 0, sizeof(*con));
+ con->private = private;
+ con->ops = ops;
atomic_set(&con->nref, 1);
con->msgr = msgr;
con_sock_state_init(con);
+ con->peer_name.type = (__u8) entity_type;
+ con->peer_name.num = cpu_to_le64(entity_num);
+
mutex_init(&con->mutex);
INIT_LIST_HEAD(&con->out_queue);
INIT_LIST_HEAD(&con->out_sent);
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -142,11 +142,9 @@ static int __open_session(struct ceph_mo
monc->sub_renew_after = jiffies; /* i.e., expired */
monc->want_next_osdmap = !!monc->want_next_osdmap;
- ceph_con_init(&monc->client->msgr, &monc->con);
- monc->con.private = monc;
- monc->con.ops = &mon_con_ops;
- monc->con.peer_name.type = CEPH_ENTITY_TYPE_MON;
- monc->con.peer_name.num = cpu_to_le64(monc->cur_mon);
+ ceph_con_init(&monc->con, monc, &mon_con_ops,
+ &monc->client->msgr,
+ CEPH_ENTITY_TYPE_MON, monc->cur_mon);
dout("open_session mon%d opening\n", monc->cur_mon);
ceph_con_open(&monc->con,
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -640,11 +640,8 @@ static struct ceph_osd *create_osd(struc
INIT_LIST_HEAD(&osd->o_osd_lru);
osd->o_incarnation = 1;
- ceph_con_init(&osdc->client->msgr, &osd->o_con);
- osd->o_con.private = osd;
- osd->o_con.ops = &osd_con_ops;
- osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
- osd->o_con.peer_name.num = cpu_to_le64(onum);
+ ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr,
+ CEPH_ENTITY_TYPE_OSD, onum);
INIT_LIST_HEAD(&osd->o_keepalive_item);
return osd;
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit 3b5ede07b55b52c3be27749d183d87257d032065)
If we fault on a lossy connection, we should still close the socket
immediately, and do so under the con mutex.
We should also take the con mutex before printing out the state bits in
the debug output.
Signed-off-by: Sage Weil <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/messenger.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -2330,22 +2330,23 @@ fault:
*/
static void ceph_fault(struct ceph_connection *con)
{
+ mutex_lock(&con->mutex);
+
pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
dout("fault %p state %lu to peer %s\n",
con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
- if (test_bit(LOSSYTX, &con->flags)) {
- dout("fault on LOSSYTX channel\n");
- goto out;
- }
-
- mutex_lock(&con->mutex);
if (test_bit(CLOSED, &con->state))
goto out_unlock;
con_close_socket(con);
+ if (test_bit(LOSSYTX, &con->flags)) {
+ dout("fault on LOSSYTX channel\n");
+ goto out_unlock;
+ }
+
if (con->in_msg) {
BUG_ON(con->in_msg->con != con);
con->in_msg->con = NULL;
@@ -2392,7 +2393,6 @@ static void ceph_fault(struct ceph_conne
out_unlock:
mutex_unlock(&con->mutex);
-out:
/*
* in case we faulted due to authentication, invalidate our
* current tickets so that we can get new ones.
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Elder <[email protected]>
(cherry picked from commit ce2c8903e76e690846a00a0284e4bd9ee954d680)
Start explicitly keeping track of the state of a ceph connection's
socket, separate from the state of the connection itself. Create
placeholder functions to encapsulate the state transitions.
--------
| NEW* | transient initial state
--------
| con_sock_state_init()
v
----------
| CLOSED | initialized, but no socket (and no
---------- TCP connection)
^ \
| \ con_sock_state_connecting()
| ----------------------
| \
+ con_sock_state_closed() \
|\ \
| \ \
| ----------- \
| | CLOSING | socket event; \
| ----------- await close \
| ^ |
| | |
| + con_sock_state_closing() |
| / \ |
| / --------------- |
| / \ v
| / --------------
| / -----------------| CONNECTING | socket created, TCP
| | / -------------- connect initiated
| | | con_sock_state_connected()
| | v
-------------
| CONNECTED | TCP connection established
-------------
Make the socket state an atomic variable, reinforcing that it's a
distinct transtion with no possible "intermediate/both" states.
This is almost certainly overkill at this point, though the
transitions into CONNECTED and CLOSING state do get called via
socket callback (the rest of the transitions occur with the
connection mutex held). We can back out the atomicity later.
Signed-off-by: Alex Elder <[email protected]>
Reviewed-by: Sage Weil<[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/ceph/messenger.h | 8 +++--
net/ceph/messenger.c | 64 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 2 deletions(-)
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -137,14 +137,18 @@ struct ceph_connection {
const struct ceph_connection_operations *ops;
struct ceph_messenger *msgr;
+
+ atomic_t sock_state;
struct socket *sock;
+ struct ceph_entity_addr peer_addr; /* peer address */
+ struct ceph_entity_addr peer_addr_for_me;
+
unsigned long flags;
unsigned long state;
const char *error_msg; /* error message, if any */
- struct ceph_entity_addr peer_addr; /* peer address */
struct ceph_entity_name peer_name; /* peer name */
- struct ceph_entity_addr peer_addr_for_me;
+
unsigned peer_features;
u32 connect_seq; /* identify the most recent connection
attempt for this connection, client */
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -29,6 +29,14 @@
* the sender.
*/
+/* State values for ceph_connection->sock_state; NEW is assumed to be 0 */
+
+#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */
+#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */
+#define CON_SOCK_STATE_CONNECTING 2 /* -> CONNECTED or -> CLOSING */
+#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */
+#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */
+
/* static tag bytes (protocol control messages) */
static char tag_msg = CEPH_MSGR_TAG_MSG;
static char tag_ack = CEPH_MSGR_TAG_ACK;
@@ -147,6 +155,55 @@ void ceph_msgr_flush(void)
}
EXPORT_SYMBOL(ceph_msgr_flush);
+/* Connection socket state transition functions */
+
+static void con_sock_state_init(struct ceph_connection *con)
+{
+ int old_state;
+
+ old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED);
+ if (WARN_ON(old_state != CON_SOCK_STATE_NEW))
+ printk("%s: unexpected old state %d\n", __func__, old_state);
+}
+
+static void con_sock_state_connecting(struct ceph_connection *con)
+{
+ int old_state;
+
+ old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING);
+ if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED))
+ printk("%s: unexpected old state %d\n", __func__, old_state);
+}
+
+static void con_sock_state_connected(struct ceph_connection *con)
+{
+ int old_state;
+
+ old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED);
+ if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING))
+ printk("%s: unexpected old state %d\n", __func__, old_state);
+}
+
+static void con_sock_state_closing(struct ceph_connection *con)
+{
+ int old_state;
+
+ old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSING);
+ if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING &&
+ old_state != CON_SOCK_STATE_CONNECTED &&
+ old_state != CON_SOCK_STATE_CLOSING))
+ printk("%s: unexpected old state %d\n", __func__, old_state);
+}
+
+static void con_sock_state_closed(struct ceph_connection *con)
+{
+ int old_state;
+
+ old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED);
+ if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED &&
+ old_state != CON_SOCK_STATE_CLOSING))
+ printk("%s: unexpected old state %d\n", __func__, old_state);
+}
/*
* socket callback functions
@@ -203,6 +260,7 @@ static void ceph_sock_state_change(struc
dout("%s TCP_CLOSE\n", __func__);
case TCP_CLOSE_WAIT:
dout("%s TCP_CLOSE_WAIT\n", __func__);
+ con_sock_state_closing(con);
if (test_and_set_bit(SOCK_CLOSED, &con->flags) == 0) {
if (test_bit(CONNECTING, &con->state))
con->error_msg = "connection failed";
@@ -213,6 +271,7 @@ static void ceph_sock_state_change(struc
break;
case TCP_ESTABLISHED:
dout("%s TCP_ESTABLISHED\n", __func__);
+ con_sock_state_connected(con);
queue_con(con);
break;
default: /* Everything else is uninteresting */
@@ -277,6 +336,7 @@ static int ceph_tcp_connect(struct ceph_
return ret;
}
con->sock = sock;
+ con_sock_state_connecting(con);
return 0;
}
@@ -343,6 +403,7 @@ static int con_close_socket(struct ceph_
sock_release(con->sock);
con->sock = NULL;
clear_bit(SOCK_CLOSED, &con->state);
+ con_sock_state_closed(con);
return rc;
}
@@ -462,6 +523,9 @@ void ceph_con_init(struct ceph_messenger
memset(con, 0, sizeof(*con));
atomic_set(&con->nref, 1);
con->msgr = msgr;
+
+ con_sock_state_init(con);
+
mutex_init(&con->mutex);
INIT_LIST_HEAD(&con->out_queue);
INIT_LIST_HEAD(&con->out_sent);
3.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sage Weil <[email protected]>
(cherry picked from commit ec87ef4309d33bd9c87a53bb5152a86ae7a65f25)
All references to the embedded ceph_connection come from the msgr
workqueue, which is drained prior to mon_client destruction. That
means we can ignore con refcounting entirely.
Signed-off-by: Sage Weil <[email protected]>
Reviewed-by: Alex Elder <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
net/ceph/mon_client.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -1037,9 +1037,23 @@ out:
mutex_unlock(&monc->mutex);
}
+/*
+ * We can ignore refcounting on the connection struct, as all references
+ * will come from the messenger workqueue, which is drained prior to
+ * mon_client destruction.
+ */
+static struct ceph_connection *con_get(struct ceph_connection *con)
+{
+ return con;
+}
+
+static void con_put(struct ceph_connection *con)
+{
+}
+
static const struct ceph_connection_operations mon_con_ops = {
- .get = ceph_con_get,
- .put = ceph_con_put,
+ .get = con_get,
+ .put = con_put,
.dispatch = dispatch,
.fault = mon_fault,
.alloc_msg = mon_alloc_msg,
On Wed, Nov 21, 2012 at 04:41:03PM -0800, Greg Kroah-Hartman wrote:
> 3.4-stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Sage Weil <[email protected]>
>
> (cherry picked from commit d59315ca8c0de00df9b363f94a2641a30961ca1c)
>
> These are no longer used. Every ceph_connection instance is embedded in
> another structure, and refcounts manipulated via the get/put ops.
>
> Signed-off-by: Sage Weil <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
[...]
>
> /*
> - * generic get/put
> - */
> -struct ceph_connection *ceph_con_get(struct ceph_connection *con)
> -{
> - int nref = __atomic_add_unless(&con->nref, 1, 0);
> -
> - dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1);
> -
> - return nref ? con : NULL;
> -}
> -
> -void ceph_con_put(struct ceph_connection *con)
> -{
> - int nref = atomic_dec_return(&con->nref);
> -
> - BUG_ON(nref < 0);
> - if (nref == 0) {
> - BUG_ON(con->sock);
> - kfree(con);
> - }
> - dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref);
> -}
> -
> -/*
> * initialize a new connection.
Although harmless in functionality not having it, may be it would be
good to also apply with this also the following commit:
commit 261030215d970c62f799e6e508e3c68fc7ec2aa9
Author: Alex Elder <[email protected]>
Date: Thu Jun 21 12:49:23 2012 -0700
libceph: drop declaration of ceph_con_get()
For some reason the declaration of ceph_con_get() and
ceph_con_put() did not get deleted in this commit:
d59315ca libceph: drop ceph_con_get/put helpers and nref member
Clean that up.
--
[]'s
Herton
On Wed, Nov 21, 2012 at 04:39:17PM -0800, Greg Kroah-Hartman wrote:
> 3.4-stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Jacob Keller <[email protected]>
>
> commit 87f4d7c1d36f44b0822053b7e5dedc31fdd0ab99 upstream.
>
> This patch updates the adjfreq callback description to include a note that the
> delta in ppb is always relative to the base frequency, and not to the current
> frequency of the hardware clock.
>
> Signed-off-by: Jacob Keller <[email protected]>
> CC: Richard Cochran <[email protected]>
> CC: John Stultz <[email protected]>
> Signed-off-by: Jeff Kirsher <[email protected]>
> Signed-off-by: David S. Miller <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
>
> ---
> include/linux/ptp_clock_kernel.h | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> --- a/include/linux/ptp_clock_kernel.h
> +++ b/include/linux/ptp_clock_kernel.h
> @@ -50,7 +50,8 @@ struct ptp_clock_request {
> * clock operations
> *
> * @adjfreq: Adjusts the frequency of the hardware clock.
> - * parameter delta: Desired period change in parts per billion.
> + * parameter delta: Desired frequency offset from nominal frequency
> + * in parts per billion
> *
> * @adjtime: Shifts the time of the hardware clock.
> * parameter delta: Desired change in nanoseconds.
>
This was marked for only 3.5 or later on the original changelog:
"CC: [email protected] [v3.5+]"
--
[]'s
Herton
On Fri, Nov 23, 2012 at 11:41:47AM -0200, Herton Ronaldo Krzesinski wrote:
> On Wed, Nov 21, 2012 at 04:41:03PM -0800, Greg Kroah-Hartman wrote:
> > 3.4-stable review patch. If anyone has any objections, please let me know.
> >
> > ------------------
> >
> > From: Sage Weil <[email protected]>
> >
> > (cherry picked from commit d59315ca8c0de00df9b363f94a2641a30961ca1c)
> >
> > These are no longer used. Every ceph_connection instance is embedded in
> > another structure, and refcounts manipulated via the get/put ops.
> >
> > Signed-off-by: Sage Weil <[email protected]>
> > Signed-off-by: Greg Kroah-Hartman <[email protected]>
> [...]
> >
> > /*
> > - * generic get/put
> > - */
> > -struct ceph_connection *ceph_con_get(struct ceph_connection *con)
> > -{
> > - int nref = __atomic_add_unless(&con->nref, 1, 0);
> > -
> > - dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1);
> > -
> > - return nref ? con : NULL;
> > -}
> > -
> > -void ceph_con_put(struct ceph_connection *con)
> > -{
> > - int nref = atomic_dec_return(&con->nref);
> > -
> > - BUG_ON(nref < 0);
> > - if (nref == 0) {
> > - BUG_ON(con->sock);
> > - kfree(con);
> > - }
> > - dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref);
> > -}
> > -
> > -/*
> > * initialize a new connection.
>
> Although harmless in functionality not having it, may be it would be
> good to also apply with this also the following commit:
>
> commit 261030215d970c62f799e6e508e3c68fc7ec2aa9
> Author: Alex Elder <[email protected]>
> Date: Thu Jun 21 12:49:23 2012 -0700
>
> libceph: drop declaration of ceph_con_get()
>
> For some reason the declaration of ceph_con_get() and
> ceph_con_put() did not get deleted in this commit:
> d59315ca libceph: drop ceph_con_get/put helpers and nref member
>
> Clean that up.
Ok, now added, thanks.
greg k-h
> -----Original Message-----
> From: Herton Ronaldo Krzesinski [mailto:[email protected]]
> Sent: Friday, November 23, 2012 4:27 PM
> To: Greg Kroah-Hartman
> Cc: [email protected]; [email protected];
> [email protected]; Keller, Jacob E; Richard Cochran; John Stultz;
> Kirsher, Jeffrey T; David S. Miller
> Subject: Re: [ 011/171] ptp: update adjfreq callback description
>
> On Wed, Nov 21, 2012 at 04:39:17PM -0800, Greg Kroah-Hartman wrote:
> > 3.4-stable review patch. If anyone has any objections, please let me
> know.
> >
> > ------------------
> >
> > From: Jacob Keller <[email protected]>
> >
> > commit 87f4d7c1d36f44b0822053b7e5dedc31fdd0ab99 upstream.
> >
> > This patch updates the adjfreq callback description to include a note
> that the
> > delta in ppb is always relative to the base frequency, and not to the
> current
> > frequency of the hardware clock.
> >
> > Signed-off-by: Jacob Keller <[email protected]>
> > CC: Richard Cochran <[email protected]>
> > CC: John Stultz <[email protected]>
> > Signed-off-by: Jeff Kirsher <[email protected]>
> > Signed-off-by: David S. Miller <[email protected]>
> > Signed-off-by: Greg Kroah-Hartman <[email protected]>
> >
> > ---
> > include/linux/ptp_clock_kernel.h | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > --- a/include/linux/ptp_clock_kernel.h
> > +++ b/include/linux/ptp_clock_kernel.h
> > @@ -50,7 +50,8 @@ struct ptp_clock_request {
> > * clock operations
> > *
> > * @adjfreq: Adjusts the frequency of the hardware clock.
> > - * parameter delta: Desired period change in parts per
> billion.
> > + * parameter delta: Desired frequency offset from nominal
> frequency
> > + * in parts per billion
> > *
> > * @adjtime: Shifts the time of the hardware clock.
> > * parameter delta: Desired change in nanoseconds.
> >
>
> This was marked for only 3.5 or later on the original changelog:
> "CC: [email protected] [v3.5+]"
>
> --
> []'s
> Herton
Originally didn't notice how far back PTP went.
-Jake