]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:35:28 +0000 (14:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:35:28 +0000 (14:35 -0700)
Pull Ceph changes from Sage Weil:
 "Lots of stuff this time around:

   - lots of cleanup and refactoring in the libceph messenger code, and
     many hard to hit races and bugs closed as a result.
   - lots of cleanup and refactoring in the rbd code from Alex Elder,
     mostly in preparation for the layering functionality that will be
     coming in 3.7.
   - some misc rbd cleanups from Josh Durgin that are finally going
     upstream
   - support for CRUSH tunables (used by newer clusters to improve the
     data placement)
   - some cleanup in our use of d_parent that Al brought up a while back
   - a random collection of fixes across the tree

  There is another patch coming that fixes up our ->atomic_open()
  behavior, but I'm going to hammer on it a bit more before sending it."

Fix up conflicts due to commits that were already committed earlier in
drivers/block/rbd.c, net/ceph/{messenger.c, osd_client.c}

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (132 commits)
  rbd: create rbd_refresh_helper()
  rbd: return obj version in __rbd_refresh_header()
  rbd: fixes in rbd_header_from_disk()
  rbd: always pass ops array to rbd_req_sync_op()
  rbd: pass null version pointer in add_snap()
  rbd: make rbd_create_rw_ops() return a pointer
  rbd: have __rbd_add_snap_dev() return a pointer
  libceph: recheck con state after allocating incoming message
  libceph: change ceph_con_in_msg_alloc convention to be less weird
  libceph: avoid dropping con mutex before fault
  libceph: verify state after retaking con lock after dispatch
  libceph: revoke mon_client messages on session restart
  libceph: fix handling of immediate socket connect failure
  ceph: update MAINTAINERS file
  libceph: be less chatty about stray replies
  libceph: clear all flags on con_close
  libceph: clean up con flags
  libceph: replace connection state bits with states
  libceph: drop unnecessary CLOSED check in socket state change callback
  libceph: close socket directly from ceph_con_close()
  ...

1  2 
MAINTAINERS
fs/ceph/dir.c
fs/ceph/super.c
fs/ceph/super.h
net/ceph/messenger.c

diff --combined MAINTAINERS
index fb036a062a5d3e3c7eefae83f3cb87d718483fcf,3afd002ef95a1f43f747da3faeb7677afa50bae5..5b44872b64ecf79162810e52602c9663364190e5
@@@ -242,6 -242,13 +242,6 @@@ W:        http://www.lesswatts.org/projects/ac
  S:    Supported
  F:    drivers/acpi/fan.c
  
 -ACPI PROCESSOR AGGREGATOR DRIVER
 -M:    Shaohua Li <shaohua.li@intel.com>
 -L:    linux-acpi@vger.kernel.org
 -W:    http://www.lesswatts.org/projects/acpi/
 -S:    Supported
 -F:    drivers/acpi/acpi_pad.c
 -
  ACPI THERMAL DRIVER
  M:    Zhang Rui <rui.zhang@intel.com>
  L:    linux-acpi@vger.kernel.org
@@@ -322,7 -329,7 +322,7 @@@ F: drivers/hwmon/adm1029.
  
  ADM8211 WIRELESS DRIVER
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  S:    Orphan
  F:    drivers/net/wireless/adm8211.*
  
@@@ -572,7 -579,7 +572,7 @@@ F: drivers/net/appletalk
  F:    net/appletalk/
  
  ARASAN COMPACT FLASH PATA CONTROLLER
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  L:    linux-ide@vger.kernel.org
  S:    Maintained
  F:    include/linux/pata_arasan_cf_data.h
@@@ -887,14 -894,6 +887,14 @@@ ARM/MAGICIAN MACHINE SUPPOR
  M:    Philipp Zabel <philipp.zabel@gmail.com>
  S:    Maintained
  
 +ARM/Marvell Armada 370 and Armada XP SOC support
 +M:    Jason Cooper <jason@lakedaemon.net>
 +M:    Andrew Lunn <andrew@lunn.ch>
 +M:    Gregory Clement <gregory.clement@free-electrons.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/mach-mvebu/
 +
  ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
  M:    Jason Cooper <jason@lakedaemon.net>
  M:    Andrew Lunn <andrew@lunn.ch>
@@@ -1078,7 -1077,7 +1078,7 @@@ F:      drivers/media/video/s5p-fimc
  ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
  M:    Kyungmin Park <kyungmin.park@samsung.com>
  M:    Kamil Debski <k.debski@samsung.com>
 -M:     Jeongtae Park <jtp.park@samsung.com>
 +M:    Jeongtae Park <jtp.park@samsung.com>
  L:    linux-arm-kernel@lists.infradead.org
  L:    linux-media@vger.kernel.org
  S:    Maintained
@@@ -1104,16 -1103,6 +1104,16 @@@ S:    Supporte
  F:    arch/arm/mach-shmobile/
  F:    drivers/sh/
  
 +ARM/SOCFPGA ARCHITECTURE
 +M:    Dinh Nguyen <dinguyen@altera.com>
 +S:    Maintained
 +F:    arch/arm/mach-socfpga/
 +
 +ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
 +M:    Dinh Nguyen <dinguyen@altera.com>
 +S:    Maintained
 +F:    drivers/clk/socfpga/
 +
  ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1186,17 -1175,6 +1186,17 @@@ S:    Maintaine
  F:    arch/arm/mach-pxa/vpac270.c
  F:    arch/arm/mach-pxa/include/mach/vpac270.h
  
 +ARM/VT8500 ARM ARCHITECTURE
 +M:    Tony Prisk <linux@prisktech.co.nz>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/mach-vt8500/
 +F:    drivers/video/vt8500lcdfb.*
 +F:    drivers/video/wm8505fb*
 +F:    drivers/video/wmt_ge_rops.*
 +F:    drivers/tty/serial/vt8500_serial.c
 +F:    drivers/rtc/rtc-vt8500-c
 +
  ARM/ZIPIT Z2 SUPPORT
  M:    Marek Vasut <marek.vasut@gmail.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1445,7 -1423,7 +1445,7 @@@ B43 WIRELESS DRIVE
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
 -W:    http://linuxwireless.org/en/users/Drivers/b43
 +W:    http://wireless.kernel.org/en/users/Drivers/b43
  S:    Maintained
  F:    drivers/net/wireless/b43/
  
@@@ -1454,7 -1432,7 +1454,7 @@@ M:      Larry Finger <Larry.Finger@lwfinger.
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  L:    linux-wireless@vger.kernel.org
  L:    b43-dev@lists.infradead.org
 -W:    http://linuxwireless.org/en/users/Drivers/b43
 +W:    http://wireless.kernel.org/en/users/Drivers/b43
  S:    Maintained
  F:    drivers/net/wireless/b43legacy/
  
@@@ -1540,11 -1518,6 +1540,11 @@@ W:    http://blackfin.uclinux.org
  S:    Supported
  F:    drivers/i2c/busses/i2c-bfin-twi.c
  
 +BLINKM RGB LED DRIVER
 +M:    Jan-Simon Moeller <jansimon.moeller@gmx.de>
 +S:    Maintained
 +F:    drivers/leds/leds-blinkm.c
 +
  BLOCK LAYER
  M:    Jens Axboe <axboe@kernel.dk>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
@@@ -1622,7 -1595,6 +1622,7 @@@ M:      Arend van Spriel <arend@broadcom.com
  M:    Franky (Zhenhui) Lin <frankyl@broadcom.com>
  M:    Kan Yan <kanyan@broadcom.com>
  L:    linux-wireless@vger.kernel.org
 +L:    brcm80211-dev-list@broadcom.com
  S:    Supported
  F:    drivers/net/wireless/brcm80211/
  
@@@ -1674,11 -1646,11 +1674,11 @@@ S:   Maintaine
  F:    drivers/gpio/gpio-bt8xx.c
  
  BTRFS FILE SYSTEM
 -M:    Chris Mason <chris.mason@oracle.com>
 +M:    Chris Mason <chris.mason@fusionio.com>
  L:    linux-btrfs@vger.kernel.org
  W:    http://btrfs.wiki.kernel.org/
  Q:    http://patchwork.kernel.org/project/linux-btrfs/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
  S:    Maintained
  F:    Documentation/filesystems/btrfs.txt
  F:    fs/btrfs/
@@@ -1771,10 -1743,10 +1771,10 @@@ F:   include/linux/can/platform
  CAPABILITIES
  M:    Serge Hallyn <serge.hallyn@canonical.com>
  L:    linux-security-module@vger.kernel.org
 -S:    Supported       
 +S:    Supported
  F:    include/linux/capability.h
  F:    security/capability.c
 -F:    security/commoncap.c 
 +F:    security/commoncap.c
  F:    kernel/capability.c
  
  CELL BROADBAND ENGINE ARCHITECTURE
@@@ -1789,15 -1761,16 +1789,16 @@@ F:   arch/powerpc/oprofile/*cell
  F:    arch/powerpc/platforms/cell/
  
  CEPH DISTRIBUTED FILE SYSTEM CLIENT
- M:    Sage Weil <sage@newdream.net>
+ M:    Sage Weil <sage@inktank.com>
  L:    ceph-devel@vger.kernel.org
- W:    http://ceph.newdream.net/
+ W:    http://ceph.com/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
  S:    Supported
  F:    Documentation/filesystems/ceph.txt
  F:    fs/ceph
  F:    net/ceph
  F:    include/linux/ceph
+ F:    include/linux/crush
  
  CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
  L:    linux-usb@vger.kernel.org
@@@ -1828,9 -1801,6 +1829,9 @@@ F:      include/linux/cfag12864b.
  CFG80211 and NL80211
  M:    Johannes Berg <johannes@sipsolutions.net>
  L:    linux-wireless@vger.kernel.org
 +W:    http://wireless.kernel.org/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
  F:    include/linux/nl80211.h
  F:    include/net/cfg80211.h
@@@ -2177,11 -2147,11 +2178,11 @@@ S:   Orpha
  F:    drivers/net/wan/pc300*
  
  CYTTSP TOUCHSCREEN DRIVER
 -M:      Javier Martinez Canillas <javier@dowhile0.org>
 -L:      linux-input@vger.kernel.org
 -S:      Maintained
 -F:      drivers/input/touchscreen/cyttsp*
 -F:      include/linux/input/cyttsp.h
 +M:    Javier Martinez Canillas <javier@dowhile0.org>
 +L:    linux-input@vger.kernel.org
 +S:    Maintained
 +F:    drivers/input/touchscreen/cyttsp*
 +F:    include/linux/input/cyttsp.h
  
  DAMA SLAVE for AX.25
  M:    Joerg Reuter <jreuter@yaina.de>
@@@ -2301,7 -2271,7 +2302,7 @@@ F:      include/linux/device-mapper.
  F:    include/linux/dm-*.h
  
  DIOLAN U2C-12 I2C DRIVER
 -M:    Guenter Roeck <guenter.roeck@ericsson.com>
 +M:    Guenter Roeck <linux@roeck-us.net>
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
  F:    drivers/i2c/busses/i2c-diolan-u2c.c
@@@ -2737,20 -2707,11 +2738,20 @@@ M:   Mimi Zohar <zohar@us.ibm.com
  S:    Supported
  F:    security/integrity/evm/
  
 +EXTERNAL CONNECTOR SUBSYSTEM (EXTCON)
 +M:    MyungJoo Ham <myungjoo.ham@samsung.com>
 +M:    Chanwoo Choi <cw00.choi@samsung.com>
 +L:    linux-kernel@vger.kernel.org
 +S:    Maintained
 +F:    drivers/extcon/
 +F:    Documentation/extcon/
 +
  EXYNOS DP DRIVER
  M:    Jingoo Han <jg1.han@samsung.com>
  L:    linux-fbdev@vger.kernel.org
  S:    Maintained
  F:    drivers/video/exynos/exynos_dp*
 +F:    include/video/exynos_dp*
  
  EXYNOS MIPI DISPLAY DRIVERS
  M:    Inki Dae <inki.dae@samsung.com>
@@@ -2970,13 -2931,6 +2971,13 @@@ F:    Documentation/power/freezing-of-task
  F:    include/linux/freezer.h
  F:    kernel/freezer.c
  
 +FRONTSWAP API
 +M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 +L:    linux-kernel@vger.kernel.org
 +S:    Maintained
 +F:    mm/frontswap.c
 +F:    include/linux/frontswap.h
 +
  FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
  M:    David Howells <dhowells@redhat.com>
  L:    linux-cachefs@redhat.com
@@@ -3156,7 -3110,8 +3157,7 @@@ S:      Maintaine
  F:    drivers/media/video/gspca/t613.c
  
  GSPCA USB WEBCAM DRIVER
 -M:    Jean-Francois Moine <moinejf@free.fr>
 -W:    http://moinejf.free.fr
 +M:    Hans de Goede <hdegoede@redhat.com>
  L:    linux-media@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
  S:    Maintained
@@@ -3184,7 -3139,7 +3185,7 @@@ F:      drivers/tty/hvc
  
  HARDWARE MONITORING
  M:    Jean Delvare <khali@linux-fr.org>
 -M:    Guenter Roeck <guenter.roeck@ericsson.com>
 +M:    Guenter Roeck <linux@roeck-us.net>
  L:    lm-sensors@lm-sensors.org
  W:    http://www.lm-sensors.org/
  T:    quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
@@@ -3469,14 -3424,13 +3470,14 @@@ S:   Supporte
  F:    drivers/idle/i7300_idle.c
  
  IEEE 802.15.4 SUBSYSTEM
 +M:    Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  M:    Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 -M:    Sergey Lapin <slapin@ossfans.org>
  L:    linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
  W:    http://apps.sourceforge.net/trac/linux-zigbee
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
  S:    Maintained
  F:    net/ieee802154/
 +F:    net/mac802154/
  F:    drivers/ieee802154/
  
  IIO SUBSYSTEM AND DRIVERS
@@@ -3697,6 -3651,14 +3698,6 @@@ T:     git git://git.kernel.org/pub/scm/lin
  S:    Supported
  F:    drivers/net/wireless/iwlwifi/
  
 -INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
 -M:    Samuel Ortiz <samuel.ortiz@intel.com>
 -M:    Intel Linux Wireless <ilw@linux.intel.com>
 -L:    linux-wireless@vger.kernel.org
 -S:    Supported
 -W:    http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
 -F:    drivers/net/wireless/iwmc3200wifi/
 -
  INTEL MANAGEMENT ENGINE (mei)
  M:    Tomas Winkler <tomas.winkler@intel.com>
  L:    linux-kernel@vger.kernel.org
@@@ -4019,8 -3981,8 +4020,8 @@@ F:      arch/ia64/include/asm/kvm
  F:    arch/ia64/kvm/
  
  KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
 -M:    Carsten Otte <cotte@de.ibm.com>
  M:    Christian Borntraeger <borntraeger@de.ibm.com>
 +M:    Cornelia Huck <cornelia.huck@de.ibm.com>
  M:    linux390@de.ibm.com
  L:    linux-s390@vger.kernel.org
  W:    http://www.ibm.com/developerworks/linux/linux390/
@@@ -4135,8 -4097,6 +4136,8 @@@ F:      drivers/scsi/53c700
  LED SUBSYSTEM
  M:    Bryan Wu <bryan.wu@canonical.com>
  M:    Richard Purdie <rpurdie@rpsys.net>
 +L:    linux-leds@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
  S:    Maintained
  F:    drivers/leds/
  F:    include/linux/leds.h
@@@ -4380,9 -4340,8 +4381,9 @@@ F:      arch/m68k/hp300
  MAC80211
  M:    Johannes Berg <johannes@sipsolutions.net>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
 +W:    http://wireless.kernel.org/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
  F:    Documentation/networking/mac80211-injection.txt
  F:    include/net/mac80211.h
@@@ -4392,9 -4351,8 +4393,9 @@@ MAC80211 PID RATE CONTRO
  M:    Stefano Brivio <stefano.brivio@polimi.it>
  M:    Mattias Nissler <mattias.nissler@gmx.de>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
 +W:    http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
  F:    net/mac80211/rc80211_pid*
  
@@@ -4454,13 -4412,6 +4455,13 @@@ S:    Orpha
  F:    drivers/video/matrox/matroxfb_*
  F:    include/linux/matroxfb.h
  
 +MAX16065 HARDWARE MONITOR DRIVER
 +M:    Guenter Roeck <linux@roeck-us.net>
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +F:    Documentation/hwmon/max16065
 +F:    drivers/hwmon/max16065.c
 +
  MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
  M:    "Hans J. Koch" <hjk@hansjkoch.de>
  L:    lm-sensors@lm-sensors.org
@@@ -4621,6 -4572,7 +4622,6 @@@ S:      Maintaine
  F:    drivers/usb/musb/
  
  MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
 -M:    Jon Mason <mason@myri.com>
  M:    Andrew Gallatin <gallatin@myri.com>
  L:    netdev@vger.kernel.org
  W:    http://www.myri.com/scs/download-Myri10GE.html
@@@ -4665,6 -4617,8 +4666,6 @@@ F:      net/sched/sch_netem.
  NETERION 10GbE DRIVERS (s2io/vxge)
  M:    Jon Mason <jdmason@kudzu.us>
  L:    netdev@vger.kernel.org
 -W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
 -W:    http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
  S:    Supported
  F:    Documentation/networking/s2io.txt
  F:    Documentation/networking/vxge.txt
@@@ -4680,8 -4634,8 +4681,8 @@@ L:      netfilter@vger.kernel.or
  L:    coreteam@netfilter.org
  W:    http://www.netfilter.org/
  W:    http://www.iptables.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-2.6.git
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next-2.6.git
 +T:    git git://1984.lsi.us.es/nf
 +T:    git git://1984.lsi.us.es/nf-next
  S:    Supported
  F:    include/linux/netfilter*
  F:    include/linux/netfilter/
@@@ -4883,7 -4837,6 +4884,7 @@@ M:      Kevin Hilman <khilman@ti.com
  L:    linux-omap@vger.kernel.org
  S:    Maintained
  F:    arch/arm/*omap*/*pm*
 +F:    drivers/cpufreq/omap-cpufreq.c
  
  OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT
  M:    Rajendra Nayak <rnayak@ti.com>
@@@ -4970,13 -4923,6 +4971,13 @@@ S:    Maintaine
  F:    drivers/usb/*/*omap*
  F:    arch/arm/*omap*/usb*
  
 +OMAP GPIO DRIVER
 +M:    Santosh Shilimkar <santosh.shilimkar@ti.com>
 +M:    Kevin Hilman <khilman@ti.com>
 +L:    linux-omap@vger.kernel.org
 +S:    Maintained
 +F:    drivers/gpio/gpio-omap.c
 +
  OMFS FILESYSTEM
  M:    Bob Copeland <me@bobcopeland.com>
  L:    linux-karma-devel@lists.sourceforge.net
@@@ -5082,7 -5028,7 +5083,7 @@@ F:      fs/ocfs2
  
  ORINOCO DRIVER
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/en/users/Drivers/orinoco
 +W:    http://wireless.kernel.org/en/users/Drivers/orinoco
  W:    http://www.nongnu.org/orinoco/
  S:    Orphan
  F:    drivers/net/wireless/orinoco/
@@@ -5204,7 -5150,7 +5205,7 @@@ F:      drivers/leds/leds-pca9532.
  F:    include/linux/leds-pca9532.h
  
  PCA9541 I2C BUS MASTER SELECTOR DRIVER
 -M:    Guenter Roeck <guenter.roeck@ericsson.com>
 +M:    Guenter Roeck <linux@roeck-us.net>
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
  F:    drivers/i2c/muxes/i2c-mux-pca9541.c
@@@ -5224,7 -5170,7 +5225,7 @@@ S:      Maintaine
  F:    drivers/firmware/pcdp.*
  
  PCI ERROR RECOVERY
 -M:     Linas Vepstas <linasvepstas@gmail.com>
 +M:    Linas Vepstas <linasvepstas@gmail.com>
  L:    linux-pci@vger.kernel.org
  S:    Supported
  F:    Documentation/PCI/pci-error-recovery.txt
@@@ -5234,7 -5180,7 +5235,7 @@@ PCI SUBSYSTE
  M:    Bjorn Helgaas <bhelgaas@google.com>
  L:    linux-pci@vger.kernel.org
  Q:    http://patchwork.ozlabs.org/project/linux-pci/list/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/linux.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
  S:    Supported
  F:    Documentation/PCI/
  F:    drivers/pci/
@@@ -5330,7 -5276,7 +5331,7 @@@ S:      Maintaine
  F:    drivers/pinctrl/
  
  PIN CONTROLLER - ST SPEAR
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.st.com/spear
@@@ -5354,7 -5300,7 +5355,7 @@@ F:      drivers/video/fb-puv3.
  F:    drivers/rtc/rtc-puv3.c
  
  PMBUS HARDWARE MONITORING DRIVERS
 -M:    Guenter Roeck <guenter.roeck@ericsson.com>
 +M:    Guenter Roeck <linux@roeck-us.net>
  L:    lm-sensors@lm-sensors.org
  W:    http://www.lm-sensors.org/
  W:    http://www.roeck-us.net/linux/drivers/
@@@ -5526,18 -5472,6 +5527,18 @@@ S:    Maintaine
  F:    Documentation/video4linux/README.pvrusb2
  F:    drivers/media/video/pvrusb2/
  
 +PWM SUBSYSTEM
 +M:    Thierry Reding <thierry.reding@avionic-design.de>
 +L:    linux-kernel@vger.kernel.org
 +S:    Maintained
 +W:    http://gitorious.org/linux-pwm
 +T:    git git://gitorious.org/linux-pwm/linux-pwm.git
 +F:    Documentation/pwm.txt
 +F:    Documentation/devicetree/bindings/pwm/
 +F:    include/linux/pwm.h
 +F:    include/linux/of_pwm.h
 +F:    drivers/pwm/
 +
  PXA2xx/PXA3xx SUPPORT
  M:    Eric Miao <eric.y.miao@gmail.com>
  M:    Russell King <linux@arm.linux.org.uk>
@@@ -5609,7 -5543,7 +5610,7 @@@ F:      Documentation/networking/LICENSE.qla
  F:    drivers/net/ethernet/qlogic/qla3xxx.*
  
  QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
 -M:    Anirban Chakraborty <anirban.chakraborty@qlogic.com>
 +M:    Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
  M:    Sony Chacko <sony.chacko@qlogic.com>
  M:    linux-driver@qlogic.com
  L:    netdev@vger.kernel.org
@@@ -5617,6 -5551,7 +5618,6 @@@ S:      Supporte
  F:    drivers/net/ethernet/qlogic/qlcnic/
  
  QLOGIC QLGE 10Gb ETHERNET DRIVER
 -M:    Anirban Chakraborty <anirban.chakraborty@qlogic.com>
  M:    Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
  M:    Ron Mercer <ron.mercer@qlogic.com>
  M:    linux-driver@qlogic.com
@@@ -5639,10 -5574,12 +5640,12 @@@ S:   Supporte
  F:    arch/hexagon/
  
  RADOS BLOCK DEVICE (RBD)
- F:    include/linux/qnxtypes.h
- M:    Yehuda Sadeh <yehuda@hq.newdream.net>
- M:    Sage Weil <sage@newdream.net>
+ M:    Yehuda Sadeh <yehuda@inktank.com>
+ M:    Sage Weil <sage@inktank.com>
+ M:    Alex Elder <elder@inktank.com>
  M:    ceph-devel@vger.kernel.org
+ W:    http://ceph.com/
+ T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git
  S:    Supported
  F:    drivers/block/rbd.c
  F:    drivers/block/rbd_types.h
@@@ -5753,7 -5690,6 +5756,7 @@@ F:      include/linux/regmap.
  
  REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
  M:    Ohad Ben-Cohen <ohad@wizery.com>
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git
  S:    Maintained
  F:    drivers/remoteproc/
  F:    Documentation/remoteproc.txt
@@@ -5762,9 -5698,6 +5765,9 @@@ F:      include/linux/remoteproc.
  RFKILL
  M:    Johannes Berg <johannes@sipsolutions.net>
  L:    linux-wireless@vger.kernel.org
 +W:    http://wireless.kernel.org/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
  S:    Maintained
  F:    Documentation/rfkill.txt
  F:    net/rfkill/
@@@ -5799,7 -5732,7 +5802,7 @@@ F:      net/rose
  RTL8180 WIRELESS DRIVER
  M:    "John W. Linville" <linville@tuxdriver.com>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtl818x/rtl8180/
@@@ -5809,7 -5742,7 +5812,7 @@@ M:      Herton Ronaldo Krzesinski <herton@ca
  M:    Hin-Tak Leung <htl10@users.sourceforge.net>
  M:    Larry Finger <Larry.Finger@lwfinger.net>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtl818x/rtl8187/
@@@ -5818,7 -5751,7 +5821,7 @@@ RTL8192CE WIRELESS DRIVE
  M:    Larry Finger <Larry.Finger@lwfinger.net>
  M:    Chaoming Li <chaoming_li@realsil.com.cn>
  L:    linux-wireless@vger.kernel.org
 -W:    http://linuxwireless.org/
 +W:    http://wireless.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
  F:    drivers/net/wireless/rtlwifi/
@@@ -5912,16 -5845,6 +5915,16 @@@ L:    linux-fbdev@vger.kernel.or
  S:    Maintained
  F:    drivers/video/s3c-fb.c
  
 +SAMSUNG MULTIFUNCTION DEVICE DRIVERS
 +M:    Sangbeom Kim <sbkim73@samsung.com>
 +L:    linux-kernel@vger.kernel.org
 +S:    Supported
 +F:    drivers/mfd/sec*.c
 +F:    drivers/regulator/s2m*.c
 +F:    drivers/regulator/s5m*.c
 +F:    drivers/rtc/rtc-sec.c
 +F:    include/linux/mfd/samsung/
 +
  SERIAL DRIVERS
  M:    Alan Cox <alan@linux.intel.com>
  L:    linux-serial@vger.kernel.org
@@@ -5929,7 -5852,7 +5932,7 @@@ S:      Maintaine
  F:    drivers/tty/serial
  
  SYNOPSYS DESIGNWARE DMAC DRIVER
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  S:    Maintained
  F:    include/linux/dw_dmac.h
  F:    drivers/dma/dw_dmac_regs.h
@@@ -5965,7 -5888,7 +5968,7 @@@ M:      Ingo Molnar <mingo@redhat.com
  M:    Peter Zijlstra <peterz@infradead.org>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched/core
  S:    Maintained
 -F:    kernel/sched*
 +F:    kernel/sched/
  F:    include/linux/sched.h
  
  SCORE ARCHITECTURE
@@@ -6077,7 -6000,7 +6080,7 @@@ S:      Maintaine
  F:    drivers/mmc/host/sdhci-s3c.c
  
  SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) ST SPEAR DRIVER
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  L:    spear-devel@list.st.com
  L:    linux-mmc@vger.kernel.org
  S:    Maintained
@@@ -6267,15 -6190,6 +6270,15 @@@ T:    git git://git.kernel.org/pub/scm/lin
  F:    include/linux/srcu*
  F:    kernel/srcu*
  
 +SMACK SECURITY MODULE
 +M:    Casey Schaufler <casey@schaufler-ca.com>
 +L:    linux-security-module@vger.kernel.org
 +W:    http://schaufler-ca.com
 +T:    git git://git.gitorious.org/smack-next/kernel.git
 +S:    Maintained
 +F:    Documentation/security/Smack.txt
 +F:    security/smack/
 +
  SMC91x ETHERNET DRIVER
  M:    Nicolas Pitre <nico@fluxnic.net>
  S:    Odd Fixes
@@@ -6289,9 -6203,9 +6292,9 @@@ F:      Documentation/hwmon/smm66
  F:    drivers/hwmon/smm665.c
  
  SMSC EMC2103 HARDWARE MONITOR DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    lm-sensors@lm-sensors.org
 -S:    Supported
 +S:    Maintained
  F:    Documentation/hwmon/emc2103
  F:    drivers/hwmon/emc2103.c
  
@@@ -6310,22 -6224,22 +6313,22 @@@ F:   Documentation/hwmon/smsc47b39
  F:    drivers/hwmon/smsc47b397.c
  
  SMSC911x ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    include/linux/smsc911x.h
  F:    drivers/net/ethernet/smsc/smsc911x.*
  
  SMSC9420 PCI ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/net/ethernet/smsc/smsc9420.*
  
  SMSC UFX6000 and UFX7000 USB to VGA DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    linux-fbdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/video/smscufx.c
  
  SN-IA64 (Itanium) SUB-PLATFORM
@@@ -6442,7 -6356,7 +6445,7 @@@ S:      Maintaine
  F:    include/linux/compiler.h
  
  SPEAR PLATFORM SUPPORT
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  M:    Shiraz Hashim <shiraz.hashim@st.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -6451,7 -6365,7 +6454,7 @@@ S:      Maintaine
  F:    arch/arm/plat-spear/
  
  SPEAR13XX MACHINE SUPPORT
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  M:    Shiraz Hashim <shiraz.hashim@st.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -6460,7 -6374,7 +6463,7 @@@ S:      Maintaine
  F:    arch/arm/mach-spear13xx/
  
  SPEAR3XX MACHINE SUPPORT
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  M:    Shiraz Hashim <shiraz.hashim@st.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -6471,7 -6385,7 +6474,7 @@@ F:      arch/arm/mach-spear3xx
  SPEAR6XX MACHINE SUPPORT
  M:    Rajeev Kumar <rajeev-dlh.kumar@st.com>
  M:    Shiraz Hashim <shiraz.hashim@st.com>
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.st.com/spear
@@@ -6479,7 -6393,7 +6482,7 @@@ S:      Maintaine
  F:    arch/arm/mach-spear6xx/
  
  SPEAR CLOCK FRAMEWORK SUPPORT
 -M:    Viresh Kumar <viresh.kumar@st.com>
 +M:     Viresh Kumar <viresh.linux@gmail.com>
  L:    spear-devel@list.st.com
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.st.com/spear
@@@ -6812,11 -6726,9 +6815,11 @@@ F:    include/linux/tifm.
  
  TI LM49xxx FAMILY ASoC CODEC DRIVERS
  M:    M R Swami Reddy <mr.swami.reddy@ti.com>
 +M:    Vishwas A Deshpande <vishwas.a.deshpande@ti.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  S:    Maintained
  F:    sound/soc/codecs/lm49453*
 +F:    sound/soc/codecs/isabelle*
  
  TI TWL4030 SERIES SOC CODEC DRIVER
  M:    Peter Ujfalusi <peter.ujfalusi@ti.com>
@@@ -6910,11 -6822,10 +6913,11 @@@ F:   include/linux/shmem_fs.
  F:    mm/shmem.c
  
  TPM DEVICE DRIVER
 -M:    Debora Velarde <debora@linux.vnet.ibm.com>
 -M:    Rajiv Andrade <srajiv@linux.vnet.ibm.com>
 +M:    Kent Yoder <key@linux.vnet.ibm.com>
 +M:    Rajiv Andrade <mail@srajiv.net>
  W:    http://tpmdd.sourceforge.net
 -M:    Marcel Selhorst <m.selhorst@sirrix.com>
 +M:    Marcel Selhorst <tpmdd@selhorst.net>
 +M:    Sirrix AG <tpmdd@sirrix.com>
  W:    http://www.sirrix.com
  L:    tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
  S:    Maintained
@@@ -7014,13 -6925,6 +7017,13 @@@ S:    Maintaine
  F:    Documentation/filesystems/ufs.txt
  F:    fs/ufs/
  
 +UHID USERSPACE HID IO DRIVER:
 +M:    David Herrmann <dh.herrmann@googlemail.com>
 +L:    linux-input@vger.kernel.org
 +S:    Maintained
 +F:    drivers/hid/uhid.c
 +F:    include/linux/uhid.h
 +
  ULTRA-WIDEBAND (UWB) SUBSYSTEM:
  L:    linux-usb@vger.kernel.org
  S:    Orphan
@@@ -7281,9 -7185,9 +7284,9 @@@ S:      Supporte
  F:    drivers/usb/serial/whiteheat*
  
  USB SMSC95XX ETHERNET DRIVER
 -M:    Steve Glendinning <steve.glendinning@smsc.com>
 +M:    Steve Glendinning <steve.glendinning@shawell.net>
  L:    netdev@vger.kernel.org
 -S:    Supported
 +S:    Maintained
  F:    drivers/net/usb/smsc95xx.*
  
  USB SN9C1xx DRIVER
@@@ -7390,11 -7294,11 +7393,11 @@@ F:   Documentation/DocBook/uio-howto.tmp
  F:    drivers/uio/
  F:    include/linux/uio*.h
  
 -UTIL-LINUX-NG PACKAGE
 +UTIL-LINUX PACKAGE
  M:    Karel Zak <kzak@redhat.com>
 -L:    util-linux-ng@vger.kernel.org
 -W:    http://kernel.org/~kzak/util-linux-ng/
 -T:    git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git
 +L:    util-linux@vger.kernel.org
 +W:    http://en.wikipedia.org/wiki/Util-linux
 +T:    git git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git
  S:    Maintained
  
  UVESAFB DRIVER
@@@ -7496,7 -7400,7 +7499,7 @@@ F:      include/linux/vlynq.
  
  VME SUBSYSTEM
  M:    Martyn Welch <martyn.welch@ge.com>
 -M:    Manohar Vanga <manohar.vanga@cern.ch>
 +M:    Manohar Vanga <manohar.vanga@gmail.com>
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  L:    devel@driverdev.osuosl.org
  S:    Maintained
@@@ -7652,9 -7556,7 +7655,9 @@@ W:      http://opensource.wolfsonmicro.com/c
  S:    Supported
  F:    Documentation/hwmon/wm83??
  F:    arch/arm/mach-s3c64xx/mach-crag6410*
 +F:    drivers/clk/clk-wm83*.c
  F:    drivers/leds/leds-wm83*.c
 +F:    drivers/gpio/gpio-*wm*.c
  F:    drivers/hwmon/wm83??-hwmon.c
  F:    drivers/input/misc/wm831x-on.c
  F:    drivers/input/touchscreen/wm831x-ts.c
diff --combined fs/ceph/dir.c
index 00894ff9246c2175b60177bab59b70456733ff01,6a66bd2d4da09a55d79e36af8e4f5de1f0653f32..f391f1e754145141235bf89d28da37d5c6aba005
@@@ -51,8 -51,7 +51,7 @@@ int ceph_init_dentry(struct dentry *den
                goto out_unlock;
        }
  
-       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
-           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
                d_set_d_op(dentry, &ceph_dentry_ops);
        else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
                d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
@@@ -79,7 -78,7 +78,7 @@@ struct inode *ceph_get_dentry_parent_in
                return NULL;
  
        spin_lock(&dentry->d_lock);
-       if (dentry->d_parent) {
+       if (!IS_ROOT(dentry)) {
                inode = dentry->d_parent->d_inode;
                ihold(inode);
        }
@@@ -576,7 -575,7 +575,7 @@@ static int is_root_ceph_dentry(struct i
   * the MDS so that it gets our 'caps wanted' value in a single op.
   */
  static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
 -                                struct nameidata *nd)
 +                                unsigned int flags)
  {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        if (err < 0)
                return ERR_PTR(err);
  
 -      /* open (but not create!) intent? */
 -      if (nd &&
 -          (nd->flags & LOOKUP_OPEN) &&
 -          !(nd->intent.open.flags & O_CREAT)) {
 -              int mode = nd->intent.open.create_mode & ~current->fs->umask;
 -              return ceph_lookup_open(dir, dentry, nd, mode, 1);
 -      }
 -
        /* can we conclude ENOENT locally? */
        if (dentry->d_inode == NULL) {
                struct ceph_inode_info *ci = ceph_inode(dir);
        return dentry;
  }
  
 +int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
 +                   struct file *file, unsigned flags, umode_t mode,
 +                   int *opened)
 +{
 +      int err;
 +      struct dentry *res = NULL;
 +
 +      if (!(flags & O_CREAT)) {
 +              if (dentry->d_name.len > NAME_MAX)
 +                      return -ENAMETOOLONG;
 +
 +              err = ceph_init_dentry(dentry);
 +              if (err < 0)
 +                      return err;
 +
 +              return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
 +      }
 +
 +      if (d_unhashed(dentry)) {
 +              res = ceph_lookup(dir, dentry, 0);
 +              if (IS_ERR(res))
 +                      return PTR_ERR(res);
 +
 +              if (res)
 +                      dentry = res;
 +      }
 +
 +      /* We don't deal with positive dentries here */
 +      if (dentry->d_inode)
 +              return finish_no_open(file, res);
 +
 +      *opened |= FILE_CREATED;
 +      err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
 +      dput(res);
 +
 +      return err;
 +}
 +
  /*
   * If we do a create but get no trace back from the MDS, follow up with
   * a lookup (the VFS expects us to link up the provided dentry).
   */
  int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
  {
 -      struct dentry *result = ceph_lookup(dir, dentry, NULL);
 +      struct dentry *result = ceph_lookup(dir, dentry, 0);
  
        if (result && !IS_ERR(result)) {
                /*
@@@ -730,9 -699,25 +729,9 @@@ static int ceph_mknod(struct inode *dir
  }
  
  static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 -                     struct nameidata *nd)
 +                     bool excl)
  {
 -      dout("create in dir %p dentry %p name '%.*s'\n",
 -           dir, dentry, dentry->d_name.len, dentry->d_name.name);
 -
 -      if (ceph_snap(dir) != CEPH_NOSNAP)
 -              return -EROFS;
 -
 -      if (nd) {
 -              BUG_ON((nd->flags & LOOKUP_OPEN) == 0);
 -              dentry = ceph_lookup_open(dir, dentry, nd, mode, 0);
 -              /* hrm, what should i do here if we get aliased? */
 -              if (IS_ERR(dentry))
 -                      return PTR_ERR(dentry);
 -              return 0;
 -      }
 -
 -      /* fall back to mknod */
 -      return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0);
 +      return ceph_mknod(dir, dentry, mode, 0);
  }
  
  static int ceph_symlink(struct inode *dir, struct dentry *dentry,
@@@ -1042,12 -1027,12 +1041,12 @@@ static int dir_lease_is_valid(struct in
  /*
   * Check if cached dentry can be trusted.
   */
 -static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 +static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
  {
        int valid = 0;
        struct inode *dir;
  
 -      if (nd && nd->flags & LOOKUP_RCU)
 +      if (flags & LOOKUP_RCU)
                return -ECHILD;
  
        dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
@@@ -1094,7 -1079,7 +1093,7 @@@ static void ceph_d_release(struct dentr
  }
  
  static int ceph_snapdir_d_revalidate(struct dentry *dentry,
 -                                        struct nameidata *nd)
 +                                        unsigned int flags)
  {
        /*
         * Eventually, we'll want to revalidate snapped metadata
@@@ -1154,7 -1139,7 +1153,7 @@@ static void ceph_d_prune(struct dentry 
        dout("ceph_d_prune %p\n", dentry);
  
        /* do we have a valid parent? */
-       if (!dentry->d_parent || IS_ROOT(dentry))
+       if (IS_ROOT(dentry))
                return;
  
        /* if we are not hashed, we don't affect D_COMPLETE */
@@@ -1371,7 -1356,6 +1370,7 @@@ const struct inode_operations ceph_dir_
        .rmdir = ceph_unlink,
        .rename = ceph_rename,
        .create = ceph_create,
 +      .atomic_open = ceph_atomic_open,
  };
  
  const struct dentry_operations ceph_dentry_ops = {
diff --combined fs/ceph/super.c
index 7076109f014dae80a85c789c3022b6465f9b70c0,2c47ecfe437301b8a8c2d4d46e19df73fd92acd0..b982239f38f91dfab38fcc093e600d5b11e5c632
@@@ -18,6 -18,7 +18,7 @@@
  #include "super.h"
  #include "mds_client.h"
  
+ #include <linux/ceph/ceph_features.h>
  #include <linux/ceph/decode.h>
  #include <linux/ceph/mon_client.h>
  #include <linux/ceph/auth.h>
@@@ -871,7 -872,7 +872,7 @@@ static struct dentry *ceph_mount(struc
  
        if (ceph_test_opt(fsc->client, NOSHARE))
                compare_super = NULL;
 -      sb = sget(fs_type, compare_super, ceph_set_super, fsc);
 +      sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc);
        if (IS_ERR(sb)) {
                res = ERR_CAST(sb);
                goto out;
diff --combined fs/ceph/super.h
index f4d5522cb619eba5f5a27842ea52277e9b3d5563,3ea48b7b98b3ccf2cf70cb802e5bb7ff8ad3793b..ebc95cc652be17bed2717d8c83f64eb39f69aed0
@@@ -612,9 -612,9 +612,9 @@@ struct ceph_snap_realm 
        u64 parent_since;   /* snapid when our current parent became so */
  
        u64 *prior_parent_snaps;      /* snaps inherited from any parents we */
-       int num_prior_parent_snaps;   /*  had prior to parent_since */
+       u32 num_prior_parent_snaps;   /*  had prior to parent_since */
        u64 *snaps;                   /* snaps specific to this realm */
-       int num_snaps;
+       u32 num_snaps;
  
        struct ceph_snap_realm *parent;
        struct list_head children;       /* list of child realms */
@@@ -806,9 -806,9 +806,9 @@@ extern int ceph_copy_from_page_vector(s
                                    loff_t off, size_t len);
  extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
  extern int ceph_open(struct inode *inode, struct file *file);
 -extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 -                                     struct nameidata *nd, int mode,
 -                                     int locked_dir);
 +extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
 +                           struct file *od, unsigned flags,
 +                           umode_t mode, int *opened);
  extern int ceph_release(struct inode *inode, struct file *filp);
  
  /* dir.c */
diff --combined net/ceph/messenger.c
index 10255e81be79d84c5428504c2a79be3180626f79,b6655b13155870b0c2769914f7faffe57ec28709..b9796750034afc093c172dc9ac92b2e864d87271
   * the sender.
   */
  
+ /*
+  * 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 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 */
+ #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 */
+ /*
+  * 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 */
+ /*
+  * 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;
  static char tag_ack = CEPH_MSGR_TAG_ACK;
@@@ -147,72 -215,130 +215,130 @@@ 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);
+       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)
+ {
+       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);
+       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)
+ {
+       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);
+       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)
+ {
+       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);
+       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)
+ {
+       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 &&
+                   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);
+ }
  
  /*
   * socket callback functions
   */
  
  /* 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 (atomic_read(&con->msgr->stopping)) {
+               return;
+       }
  
        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 (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) {
                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))
-               return;
        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");
-               if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) {
-                       if (test_bit(CONNECTING, &con->state))
-                               con->error_msg = "connection failed";
-                       else
-                               con->error_msg = "socket closed";
-                       queue_con(con);
-               }
+               dout("%s TCP_CLOSE_WAIT\n", __func__);
+               con_sock_state_closing(con);
+               set_bit(CON_FLAG_SOCK_CLOSED, &con->flags);
+               queue_con(con);
                break;
        case TCP_ESTABLISHED:
-               dout("ceph_state_change TCP_ESTABLISHED\n");
+               dout("%s TCP_ESTABLISHED\n", __func__);
+               con_sock_state_connected(con);
                queue_con(con);
                break;
        default:        /* Everything else is uninteresting */
@@@ -228,9 -354,9 +354,9 @@@ static void set_sock_callbacks(struct s
  {
        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;
  }
  
  
@@@ -262,6 -388,7 +388,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) {
                return ret;
        }
        con->sock = sock;
        return 0;
  }
  
@@@ -333,16 -459,24 +459,24 @@@ static int ceph_tcp_sendpage(struct soc
   */
  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;
-       set_bit(SOCK_CLOSED, &con->state);
-       rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR);
-       sock_release(con->sock);
-       con->sock = NULL;
-       clear_bit(SOCK_CLOSED, &con->state);
+       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
+        * 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(CON_FLAG_SOCK_CLOSED, &con->flags);
+       con_sock_state_closed(con);
        return rc;
  }
  
  static void ceph_msg_remove(struct ceph_msg *msg)
  {
        list_del_init(&msg->list_head);
+       BUG_ON(msg->con == NULL);
+       msg->con->ops->put(msg->con);
+       msg->con = NULL;
        ceph_msg_put(msg);
  }
  static void ceph_msg_remove_list(struct list_head *head)
@@@ -372,8 -510,11 +510,11 @@@ static void reset_connection(struct cep
        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;
+               con->ops->put(con);
        }
  
        con->connect_seq = 0;
   */
  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));
-       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);
-       mutex_lock(&con->mutex);
+       con->state = CON_STATE_CLOSED;
+       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;
        cancel_delayed_work(&con->work);
+       con_close_socket(con);
        mutex_unlock(&con->mutex);
-       queue_con(con);
  }
  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)
  {
+       mutex_lock(&con->mutex);
        dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr));
-       set_bit(OPENING, &con->state);
-       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);
        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);
@@@ -429,43 -582,27 +582,27 @@@ bool ceph_con_opened(struct ceph_connec
        return con->connect_seq > 0;
  }
  
- /*
-  * 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_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)
  {
        dout("con_init %p\n", con);
        memset(con, 0, sizeof(*con));
-       atomic_set(&con->nref, 1);
+       con->private = private;
+       con->ops = ops;
        con->msgr = msgr;
+       con_sock_state_init(con);
        mutex_init(&con->mutex);
        INIT_LIST_HEAD(&con->out_queue);
        INIT_LIST_HEAD(&con->out_sent);
        INIT_DELAYED_WORK(&con->work, con_work);
+       con->state = CON_STATE_CLOSED;
  }
  EXPORT_SYMBOL(ceph_con_init);
  
@@@ -486,14 -623,14 +623,14 @@@ static u32 get_global_seq(struct ceph_m
        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;
        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;
+       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;
+ #ifdef CONFIG_BLOCK
+       if (msg->bio)
+               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 */
+ }
  /*
   * Prepare footer for currently outgoing message, and finish things
   * off.  Assumes out_kvec* are already valid.. we just add on to the end.
@@@ -516,6 -700,8 +700,8 @@@ static void prepare_write_message_foote
        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;
@@@ -534,7 -720,7 +720,7 @@@ static void prepare_write_message(struc
        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;
  
         * 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);
        }
  
+       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);
                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),
        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 */
        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);
                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->state);
+       set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
  }
  
  /*
@@@ -630,16 -805,16 +809,16 @@@ static void prepare_write_ack(struct ce
             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.. */
-       set_bit(WRITE_PENDING, &con->state);
+       set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
  }
  
  /*
  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);
-       set_bit(WRITE_PENDING, &con->state);
+       con_out_kvec_reset(con);
+       con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive);
+       set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
  }
  
  /*
@@@ -665,27 -840,21 +844,21 @@@ static struct ceph_auth_handshake *get_
        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->state))
+       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;
  }
  
   */
  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;
-       set_bit(WRITE_PENDING, &con->state);
+       set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
  }
  
  static int prepare_write_connect(struct ceph_connection *con)
        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_reset(con);
+       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;
-       set_bit(WRITE_PENDING, &con->state);
+       set_bit(CON_FLAG_WRITE_PENDING, &con->flags);
  
        return 0;
  }
@@@ -797,30 -967,34 +971,34 @@@ out
        return ret;  /* done! */
  }
  
- #ifdef CONFIG_BLOCK
static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg)
+ static void out_msg_pos_next(struct ceph_connection *con, struct page *page,
                      size_t len, size_t sent, bool in_trail)
  {
-       if (!bio) {
-               *iter = NULL;
-               *seg = 0;
-               return;
-       }
-       *iter = bio;
-       *seg = bio->bi_idx;
- }
+       struct ceph_msg *msg = con->out_msg;
  
- static void iter_bio_next(struct bio **bio_iter, int *seg)
- {
-       if (*bio_iter == NULL)
-               return;
+       BUG_ON(!msg);
+       BUG_ON(!sent);
  
-       BUG_ON(*seg >= (*bio_iter)->bi_vcnt);
+       con->out_msg_pos.data_pos += sent;
+       con->out_msg_pos.page_pos += sent;
+       if (sent < len)
+               return;
  
-       (*seg)++;
-       if (*seg == (*bio_iter)->bi_vcnt)
-               init_bio_iter((*bio_iter)->bi_next, bio_iter, seg);
- }
+       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);
  #endif
+ }
  
  /*
   * Write as much message data payload as we can.  If we finish, queue
@@@ -837,41 -1011,36 +1015,36 @@@ static int write_partial_msg_pages(stru
        bool do_datacrc = !con->msgr->nocrc;
        int ret;
        int total_max_write;
-       int in_trail = 0;
-       size_t trail_len = (msg->trail ? msg->trail->length : 0);
+       bool in_trail = false;
+       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, 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
-       if (msg->bio && !msg->bio_iter)
-               init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg);
- #endif
+       /*
+        * 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 = 1;
+               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,
                                                struct page, lru);
-                       max_write = PAGE_SIZE;
                } else if (msg->pages) {
                        page = msg->pages[con->out_msg_pos.page];
                } else if (msg->pagelist) {
  
                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 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);
-                       con->out_msg->footer.data_crc = cpu_to_le32(crc);
+                       crc = crc32c(crc, base, len);
+                       msg->footer.data_crc = cpu_to_le32(crc);
                        con->out_msg_pos.did_page_crc = true;
                }
                ret = ceph_tcp_sendpage(con->sock, page,
                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;
-       ceph_con_out_kvec_reset(con);
+               msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
+       con_out_kvec_reset(con);
        prepare_write_message_footer(con);
        ret = 1;
  out:
@@@ -1351,20 -1503,14 +1507,14 @@@ static int process_banner(struct ceph_c
                     ceph_pr_addr(&con->msgr->inst.addr.in_addr));
        }
  
-       set_bit(NEGOTIATING, &con->state);
-       prepare_read_connect(con);
        return 0;
  }
  
  static void fail_protocol(struct ceph_connection *con)
  {
        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);
+       BUG_ON(con->state != CON_STATE_NEGOTIATING);
+       con->state = CON_STATE_CLOSED;
  }
  
  static int process_connect(struct ceph_connection *con)
                        return -1;
                }
                con->auth_retry = 1;
-               ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
                        return ret;
                       ENTITY_NAME(con->peer_name),
                       ceph_pr_addr(&con->peer_addr.in_addr));
                reset_connection(con);
-               ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
                        return ret;
                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;
  
                     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);
                ret = prepare_write_connect(con);
                if (ret < 0)
                        return ret;
                     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);
                ret = prepare_write_connect(con);
                if (ret < 0)
                        return ret;
                        fail_protocol(con);
                        return -1;
                }
-               clear_bit(CONNECTING, &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;
                        le32_to_cpu(con->in_reply.connect_seq));
  
                if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY)
-                       set_bit(LOSSYTX, &con->state);
+                       set_bit(CON_FLAG_LOSSYTX, &con->flags);
+               con->delay = 0;      /* reset backoff memory */
  
                prepare_read_tag(con);
                break;
@@@ -1587,10 -1733,7 +1737,7 @@@ 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 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,
@@@ -1633,9 -1776,6 +1780,6 @@@ static int read_partial_message_bio(str
        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));
  
@@@ -1672,7 -1812,6 +1816,6 @@@ static int read_partial_message(struct 
        int ret;
        unsigned int front_len, middle_len, data_len;
        bool do_datacrc = !con->msgr->nocrc;
-       int skip;
        u64 seq;
        u32 crc;
  
  
        /* 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);
-               skip = 0;
-               con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip);
+               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");
                        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 */
                if (m->middle)
                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 */
                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) {
                                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);
@@@ -1837,8 -1978,11 +1982,11 @@@ 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;
+       con->ops->put(con);
  
        /* if first message, set peer_name */
        if (con->peer_name.type == 0)
        con->ops->dispatch(con, msg);
  
        mutex_lock(&con->mutex);
-       prepare_read_tag(con);
  }
  
  
@@@ -1870,22 -2013,19 +2017,19 @@@ static int try_write(struct ceph_connec
  {
        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);
  
        /* open the socket first? */
-       if (con->sock == NULL) {
-               ceph_con_out_kvec_reset(con);
+       if (con->state == CON_STATE_PREOPEN) {
+               BUG_ON(con->sock);
+               con->state = CON_STATE_CONNECTING;
+               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;
@@@ -1932,7 -2072,7 +2076,7 @@@ more_kvec
        }
  
  do_next:
-       if (!test_bit(CONNECTING, &con->state)) {
+       if (con->state == CON_STATE_OPEN) {
                /* is anything else pending? */
                if (!list_empty(&con->out_queue)) {
                        prepare_write_message(con);
                        prepare_write_ack(con);
                        goto more;
                }
-               if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) {
+               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->state);
+       clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
        dout("try_write nothing else to write.\n");
        ret = 0;
  out:
@@@ -1966,38 -2107,42 +2111,42 @@@ static int try_read(struct ceph_connect
  {
        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;
+       if (con->state == CON_STATE_CONNECTING) {
+               dout("try_read connecting\n");
+               ret = read_partial_banner(con);
+               if (ret <= 0)
+                       goto out;
+               ret = process_banner(con);
+               if (ret < 0)
+                       goto out;
+               BUG_ON(con->state != CON_STATE_CONNECTING);
+               con->state = CON_STATE_NEGOTIATING;
+               /* 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(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;
-               }
+       if (con->state == CON_STATE_NEGOTIATING) {
+               dout("try_read negotiating\n");
                ret = read_partial_connect(con);
                if (ret <= 0)
                        goto out;
                goto more;
        }
  
+       BUG_ON(con->state != CON_STATE_OPEN);
        if (con->in_base_pos < 0) {
                /*
                 * skipping + discarding content.
                        prepare_read_ack(con);
                        break;
                case CEPH_MSGR_TAG_CLOSE:
-                       set_bit(CLOSED, &con->state);   /* fixme */
+                       con_close_socket(con);
+                       con->state = CON_STATE_CLOSED;
                        goto out;
                default:
                        goto bad_tag;
                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) {
@@@ -2091,12 -2241,6 +2245,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;
@@@ -2121,7 -2265,26 +2269,26 @@@ static void con_work(struct work_struc
  
        mutex_lock(&con->mutex);
  restart:
-       if (test_and_clear_bit(BACKOFF, &con->state)) {
+       if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) {
+               switch (con->state) {
+               case CON_STATE_CONNECTING:
+                       con->error_msg = "connection failed";
+                       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;
+       }
+       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))) {
                }
        }
  
-       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)) { /* e.g. if we are replaced */
-               dout("con_work CLOSED\n");
-               con_close_socket(con);
+       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");
-               con_close_socket(con);
+               BUG_ON(con->sock);
        }
  
-       if (test_and_clear_bit(SOCK_CLOSED, &con->state))
-               goto fault;
        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);
@@@ -2172,7 -2335,6 +2339,6 @@@ done_unlocked
        return;
  
  fault:
-       mutex_unlock(&con->mutex);
        ceph_fault(con);     /* error/fault path */
        goto done_unlocked;
  }
   * exponential backoff
   */
  static void ceph_fault(struct ceph_connection *con)
+       __releases(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->state)) {
-               dout("fault on LOSSYTX channel\n");
-               goto out;
-       }
-       mutex_lock(&con->mutex);
-       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(CON_FLAG_LOSSYTX, &con->flags)) {
+               dout("fault on LOSSYTX channel, marking CLOSED\n");
+               con->state = CON_STATE_CLOSED;
+               goto out_unlock;
+       }
        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;
+               con->ops->put(con);
        }
  
        /* Requeue anything that hasn't been acked */
        /* 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(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) {
                dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con);
-               clear_bit(WRITE_PENDING, &con->state);
-               set_bit(STANDBY, &con->state);
+               clear_bit(CON_FLAG_WRITE_PENDING, &con->flags);
+               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)
                         * that when con_work restarts we schedule the
                         * delay then.
                         */
-                       set_bit(BACKOFF, &con->state);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
        }
  
  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.
  
  
  /*
-  * 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;
  
        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);
+       atomic_set(&msgr->stopping, 0);
  
- 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)
  {
        /* come back from STANDBY? */
-       if (test_and_clear_bit(STANDBY, &con->state)) {
-               mutex_lock(&con->mutex);
+       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->state));
-               WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state));
-               mutex_unlock(&con->mutex);
+               WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags));
+               WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags));
        }
  }
  
   */
  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 (con->state == CON_STATE_CLOSED) {
+               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);
        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,
             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->state) == 0)
+       if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0)
                queue_con(con);
  }
  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("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);
-               ceph_msg_put(msg);
+               BUG_ON(msg->con == NULL);
+               msg->con->ops->put(msg->con);
+               msg->con = NULL;
                msg->hdr.seq = 0;
+               ceph_msg_put(msg);
        }
        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;
                        con->out_kvec_is_msg = false;
                }
-               ceph_msg_put(msg);
                msg->hdr.seq = 0;
+               ceph_msg_put(msg);
        }
        mutex_unlock(&con->mutex);
  }
  /*
   * 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 int front_len = le32_to_cpu(con->in_hdr.front_len);
                unsigned int middle_len = le32_to_cpu(con->in_hdr.middle_len);
                unsigned int 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 -
                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);
  }
  void ceph_con_keepalive(struct ceph_connection *con)
  {
        dout("con_keepalive %p\n", con);
+       mutex_lock(&con->mutex);
        clear_standby(con);
-       if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 &&
-           test_and_set_bit(WRITE_PENDING, &con->state) == 0)
+       mutex_unlock(&con->mutex);
+       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);
@@@ -2431,6 -2613,8 +2617,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;
@@@ -2526,46 -2710,77 +2714,77 @@@ static int ceph_alloc_middle(struct cep
  }
  
  /*
-  * 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 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 struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con,
-                               struct ceph_msg_header *hdr,
-                               int *skip)
+ 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);
-       struct ceph_msg *msg = NULL;
-       int ret;
+       int ret = 0;
+       BUG_ON(con->in_msg != NULL);
  
        if (con->ops->alloc_msg) {
+               struct ceph_msg *msg;
                mutex_unlock(&con->mutex);
                msg = con->ops->alloc_msg(con, hdr, skip);
                mutex_lock(&con->mutex);
-               if (!msg || *skip)
-                       return NULL;
+               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);
+               }
+               if (*skip) {
+                       con->in_msg = NULL;
+                       return 0;
+               }
+               if (!con->in_msg) {
+                       con->error_msg =
+                               "error allocating memory for incoming message";
+                       return -ENOMEM;
+               }
        }
-       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 -ENOMEM;
                }
-               msg->page_alignment = le16_to_cpu(hdr->data_off);
+               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);
        }
-       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 ret;
  }