瀏覽代碼

Merge branch 'for-2.6.38/core' into for-next

Jens Axboe 14 年之前
父節點
當前提交
c4ffa14684
共有 96 個文件被更改,包括 1311 次插入1453 次删除
  1. 4 3
      Documentation/arm/OMAP/DSS
  2. 27 0
      Documentation/cgroups/blkio-controller.txt
  3. 10 0
      Documentation/feature-removal-schedule.txt
  4. 3 2
      MAINTAINERS
  5. 1 1
      Makefile
  6. 16 16
      arch/arm/Kconfig
  7. 2 3
      arch/arm/mach-omap1/devices.c
  8. 2 0
      arch/arm/mach-omap1/include/mach/camera.h
  9. 0 3
      arch/arm/mach-omap2/board-devkit8000.c
  10. 1 1
      arch/arm/mach-s3c64xx/Kconfig
  11. 6 0
      arch/arm/mach-shmobile/board-ap4evb.c
  12. 1 1
      arch/arm/mach-shmobile/intc-sh7372.c
  13. 2 0
      arch/arm/plat-omap/dma.c
  14. 83 20
      arch/x86/pci/acpi.c
  15. 0 4
      block/blk-cgroup.c
  16. 5 5
      block/blk-core.c
  17. 30 26
      block/cfq-iosched.c
  18. 3 2
      block/ioctl.c
  19. 0 2
      drivers/block/drbd/drbd_int.h
  20. 2 5
      drivers/block/drbd/drbd_main.c
  21. 36 67
      drivers/block/drbd/drbd_nl.c
  22. 8 14
      drivers/block/pktcdvd.c
  23. 4 4
      drivers/char/i8k.c
  24. 4 10
      drivers/char/raw.c
  25. 1 1
      drivers/hwmon/amc6821.c
  26. 2 2
      drivers/hwmon/lm93.c
  27. 14 5
      drivers/hwmon/lm95241.c
  28. 1 1
      drivers/hwmon/max6650.c
  29. 174 33
      drivers/hwmon/w83795.c
  30. 12 0
      drivers/i2c/i2c-core.c
  31. 0 1
      drivers/i2c/i2c-mux.c
  32. 11 9
      drivers/md/dm-table.c
  33. 2 2
      drivers/md/dm.c
  34. 4 12
      drivers/md/md.c
  35. 0 1
      drivers/media/common/saa7146_i2c.c
  36. 0 2
      drivers/media/video/imx074.c
  37. 0 1
      drivers/media/video/ir-kbd-i2c.c
  38. 0 2
      drivers/media/video/ov6650.c
  39. 0 1
      drivers/misc/apds9802als.c
  40. 5 5
      drivers/mtd/devices/block2mtd.c
  41. 49 21
      drivers/pci/bus.c
  42. 6 0
      drivers/pci/hotplug/ibmphp_ebda.c
  43. 17 6
      drivers/pci/pci-sysfs.c
  44. 12 0
      drivers/pci/pci.c
  45. 6 1
      drivers/pci/pci.h
  46. 1 1
      drivers/pci/proc.c
  47. 2 2
      drivers/rtc/rtc-sh.c
  48. 1 1
      drivers/s390/block/dasd_genhd.c
  49. 2 2
      drivers/sh/clk/core.c
  50. 1 1
      drivers/sh/intc/virq.c
  51. 0 4
      drivers/staging/olpc_dcon/olpc_dcon.c
  52. 2 5
      drivers/usb/gadget/storage_common.c
  53. 13 4
      drivers/video/omap2/vram.c
  54. 0 1
      drivers/video/riva/rivafb-i2c.c
  55. 4 1
      drivers/video/sh_mobile_hdmi.c
  56. 12 9
      drivers/video/sh_mobile_lcdcfb.c
  57. 6 2
      drivers/video/sis/sis_main.c
  58. 221 487
      fs/block_dev.c
  59. 16 12
      fs/btrfs/volumes.c
  60. 1 1
      fs/btrfs/volumes.h
  61. 2 10
      fs/ext3/super.c
  62. 2 10
      fs/ext4/super.c
  63. 4 42
      fs/gfs2/export.c
  64. 10 11
      fs/gfs2/glock.c
  65. 35 117
      fs/gfs2/inode.c
  66. 3 1
      fs/gfs2/inode.h
  67. 4 4
      fs/gfs2/ops_fstype.c
  68. 46 45
      fs/gfs2/rgrp.c
  69. 5 12
      fs/jfs/jfs_logmgr.c
  70. 4 3
      fs/logfs/dev_bdev.c
  71. 4 4
      fs/nilfs2/super.c
  72. 1 1
      fs/ocfs2/cluster/heartbeat.c
  73. 3 3
      fs/ocfs2/ocfs2.h
  74. 10 1
      fs/partitions/check.c
  75. 7 14
      fs/reiserfs/journal.c
  76. 10 9
      fs/super.c
  77. 3 2
      fs/xfs/linux-2.6/xfs_super.c
  78. 13 12
      include/linux/fs.h
  79. 0 1
      include/linux/fsl-diu-fb.h
  80. 0 22
      include/linux/i2c-id.h
  81. 1 1
      include/linux/i2c.h
  82. 1 244
      include/linux/kernel.h
  83. 248 0
      include/linux/printk.h
  84. 4 5
      include/linux/security.h
  85. 1 1
      include/linux/sh_intc.h
  86. 3 3
      include/trace/events/block.h
  87. 3 2
      kernel/power/swap.c
  88. 14 1
      kernel/printk.c
  89. 6 6
      kernel/trace/blktrace.c
  90. 2 1
      mm/slub.c
  91. 4 3
      mm/swapfile.c
  92. 5 0
      security/capability.c
  93. 0 21
      security/commoncap.c
  94. 2 2
      security/security.c
  95. 1 5
      security/selinux/hooks.c
  96. 2 6
      security/smack/smack_lsm.c

+ 4 - 3
Documentation/arm/OMAP/DSS

@@ -255,9 +255,10 @@ framebuffer parameters.
 Kernel boot arguments
 Kernel boot arguments
 ---------------------
 ---------------------
 
 
-vram=<size>
-	- Amount of total VRAM to preallocate. For example, "10M". omapfb
-	  allocates memory for framebuffers from VRAM.
+vram=<size>[,<physaddr>]
+	- Amount of total VRAM to preallocate and optionally a physical start
+	  memory address. For example, "10M". omapfb allocates memory for
+	  framebuffers from VRAM.
 
 
 omapfb.mode=<display>:<mode>[,...]
 omapfb.mode=<display>:<mode>[,...]
 	- Default video mode for specified displays. For example,
 	- Default video mode for specified displays. For example,

+ 27 - 0
Documentation/cgroups/blkio-controller.txt

@@ -89,6 +89,33 @@ Throttling/Upper Limit policy
 
 
  Limits for writes can be put using blkio.write_bps_device file.
  Limits for writes can be put using blkio.write_bps_device file.
 
 
+Hierarchical Cgroups
+====================
+- Currently none of the IO control policy supports hierarhical groups. But
+  cgroup interface does allow creation of hierarhical cgroups and internally
+  IO policies treat them as flat hierarchy.
+
+  So this patch will allow creation of cgroup hierarhcy but at the backend
+  everything will be treated as flat. So if somebody created a hierarchy like
+  as follows.
+
+			root
+			/  \
+		     test1 test2
+			|
+		     test3
+
+  CFQ and throttling will practically treat all groups at same level.
+
+				pivot
+			     /  |   \  \
+			root  test1 test2  test3
+
+  Down the line we can implement hierarchical accounting/control support
+  and also introduce a new cgroup file "use_hierarchy" which will control
+  whether cgroup hierarchy is viewed as flat or hierarchical by the policy..
+  This is how memory controller also has implemented the things.
+
 Various user visible config options
 Various user visible config options
 ===================================
 ===================================
 CONFIG_BLK_CGROUP
 CONFIG_BLK_CGROUP

+ 10 - 0
Documentation/feature-removal-schedule.txt

@@ -554,3 +554,13 @@ Why:    This is a legacy interface which have been replaced by a more
 Who:    NeilBrown <neilb@suse.de>
 Who:    NeilBrown <neilb@suse.de>
 
 
 ----------------------------
 ----------------------------
+
+What:	i2c_adapter.id
+When:	June 2011
+Why:	This field is deprecated. I2C device drivers shouldn't change their
+	behavior based on the underlying I2C adapter. Instead, the I2C
+	adapter driver should instantiate the I2C devices and provide the
+	needed platform-specific information.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+----------------------------

+ 3 - 2
MAINTAINERS

@@ -945,7 +945,7 @@ M:	Magnus Damm <magnus.damm@gmail.com>
 L:	linux-sh@vger.kernel.org
 L:	linux-sh@vger.kernel.org
 W:	http://oss.renesas.com
 W:	http://oss.renesas.com
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/genesis-2.6.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git rmobile-latest
 S:	Supported
 S:	Supported
 F:	arch/arm/mach-shmobile/
 F:	arch/arm/mach-shmobile/
 F:	drivers/sh/
 F:	drivers/sh/
@@ -2435,6 +2435,7 @@ F:	drivers/net/wan/sdla.c
 FRAMEBUFFER LAYER
 FRAMEBUFFER LAYER
 L:	linux-fbdev@vger.kernel.org
 L:	linux-fbdev@vger.kernel.org
 W:	http://linux-fbdev.sourceforge.net/
 W:	http://linux-fbdev.sourceforge.net/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
 S:	Orphan
 S:	Orphan
 F:	Documentation/fb/
 F:	Documentation/fb/
 F:	drivers/video/fb*
 F:	drivers/video/fb*
@@ -5705,7 +5706,7 @@ M:	Paul Mundt <lethal@linux-sh.org>
 L:	linux-sh@vger.kernel.org
 L:	linux-sh@vger.kernel.org
 W:	http://www.linux-sh.org
 W:	http://www.linux-sh.org
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git sh-latest
 S:	Supported
 S:	Supported
 F:	Documentation/sh/
 F:	Documentation/sh/
 F:	arch/sh/
 F:	arch/sh/

+ 1 - 1
Makefile

@@ -1,7 +1,7 @@
 VERSION = 2
 VERSION = 2
 PATCHLEVEL = 6
 PATCHLEVEL = 6
 SUBLEVEL = 37
 SUBLEVEL = 37
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Flesh-Eating Bats with Fangs
 NAME = Flesh-Eating Bats with Fangs
 
 
 # *DOCUMENTATION*
 # *DOCUMENTATION*

+ 16 - 16
arch/arm/Kconfig

@@ -646,7 +646,7 @@ config ARCH_S3C2410
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_CPUFREQ
 	select HAVE_CLK
 	select HAVE_CLK
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_USES_GETTIMEOFFSET
-	select HAVE_S3C2410_I2C
+	select HAVE_S3C2410_I2C if I2C
 	help
 	help
 	  Samsung S3C2410X CPU based systems, such as the Simtec Electronics
 	  Samsung S3C2410X CPU based systems, such as the Simtec Electronics
 	  BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
 	  BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -676,8 +676,8 @@ config ARCH_S3C64XX
 	select S3C_DEV_NAND
 	select S3C_DEV_NAND
 	select USB_ARCH_HAS_OHCI
 	select USB_ARCH_HAS_OHCI
 	select SAMSUNG_GPIOLIB_4BIT
 	select SAMSUNG_GPIOLIB_4BIT
-	select HAVE_S3C2410_I2C
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	help
 	  Samsung S3C64XX series based systems
 	  Samsung S3C64XX series based systems
 
 
@@ -686,10 +686,10 @@ config ARCH_S5P64X0
 	select CPU_V6
 	select CPU_V6
 	select GENERIC_GPIO
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_CLK
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_USES_GETTIMEOFFSET
-	select HAVE_S3C2410_I2C
-	select HAVE_S3C_RTC
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C_RTC if RTC_CLASS
 	help
 	help
 	  Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
 	  Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
 	  SMDK6450.
 	  SMDK6450.
@@ -700,7 +700,7 @@ config ARCH_S5P6442
 	select GENERIC_GPIO
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_CLK
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_USES_GETTIMEOFFSET
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	help
 	  Samsung S5P6442 CPU based systems
 	  Samsung S5P6442 CPU based systems
 
 
@@ -711,9 +711,9 @@ config ARCH_S5PC100
 	select CPU_V7
 	select CPU_V7
 	select ARM_L1_CACHE_SHIFT_6
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_USES_GETTIMEOFFSET
-	select HAVE_S3C2410_I2C
-	select HAVE_S3C_RTC
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C_RTC if RTC_CLASS
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	help
 	  Samsung S5PC100 series based systems
 	  Samsung S5PC100 series based systems
 
 
@@ -726,9 +726,9 @@ config ARCH_S5PV210
 	select ARM_L1_CACHE_SHIFT_6
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_CPUFREQ
 	select ARCH_USES_GETTIMEOFFSET
 	select ARCH_USES_GETTIMEOFFSET
-	select HAVE_S3C2410_I2C
-	select HAVE_S3C_RTC
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C_RTC if RTC_CLASS
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 	  Samsung S5PV210/S5PC110 series based systems
 
 
@@ -739,9 +739,9 @@ config ARCH_S5PV310
 	select GENERIC_GPIO
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS
-	select HAVE_S3C_RTC
-	select HAVE_S3C2410_I2C
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C_RTC if RTC_CLASS
+	select HAVE_S3C2410_I2C if I2C
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	help
 	  Samsung S5PV310 series based systems
 	  Samsung S5PV310 series based systems
 
 

+ 2 - 3
arch/arm/mach-omap1/devices.c

@@ -321,10 +321,9 @@ static struct platform_device omap_wdt_device = {
 static int __init omap_init_wdt(void)
 static int __init omap_init_wdt(void)
 {
 {
 	if (!cpu_is_omap16xx())
 	if (!cpu_is_omap16xx())
-		return;
+		return -ENODEV;
 
 
-	platform_device_register(&omap_wdt_device);
-	return 0;
+	return platform_device_register(&omap_wdt_device);
 }
 }
 subsys_initcall(omap_init_wdt);
 subsys_initcall(omap_init_wdt);
 #endif
 #endif

+ 2 - 0
arch/arm/mach-omap1/include/mach/camera.h

@@ -1,6 +1,8 @@
 #ifndef __ASM_ARCH_CAMERA_H_
 #ifndef __ASM_ARCH_CAMERA_H_
 #define __ASM_ARCH_CAMERA_H_
 #define __ASM_ARCH_CAMERA_H_
 
 
+#include <media/omap1_camera.h>
+
 void omap1_camera_init(void *);
 void omap1_camera_init(void *);
 
 
 static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)
 static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)

+ 0 - 3
arch/arm/mach-omap2/board-devkit8000.c

@@ -242,9 +242,6 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 	mmc[0].gpio_cd = gpio + 0;
 	mmc[0].gpio_cd = gpio + 0;
 	omap2_hsmmc_init(mmc);
 	omap2_hsmmc_init(mmc);
 
 
-	/* link regulators to MMC adapters */
-	devkit8000_vmmc1_supply.dev = mmc[0].dev;
-
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 
 

+ 1 - 1
arch/arm/mach-s3c64xx/Kconfig

@@ -143,7 +143,7 @@ config MACH_SMDK6410
 	select S3C_DEV_USB_HSOTG
 	select S3C_DEV_USB_HSOTG
 	select S3C_DEV_WDT
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_KEYPAD
 	select SAMSUNG_DEV_KEYPAD
-	select HAVE_S3C2410_WATCHDOG
+	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_I2C1
 	select S3C64XX_SETUP_I2C1
 	select S3C64XX_SETUP_IDE
 	select S3C64XX_SETUP_IDE

+ 6 - 0
arch/arm/mach-shmobile/board-ap4evb.c

@@ -163,11 +163,13 @@ static struct mtd_partition nor_flash_partitions[] = {
 		.name		= "loader",
 		.name		= "loader",
 		.offset		= 0x00000000,
 		.offset		= 0x00000000,
 		.size		= 512 * 1024,
 		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
 	},
 	},
 	{
 	{
 		.name		= "bootenv",
 		.name		= "bootenv",
 		.offset		= MTDPART_OFS_APPEND,
 		.offset		= MTDPART_OFS_APPEND,
 		.size		= 512 * 1024,
 		.size		= 512 * 1024,
+		.mask_flags	= MTD_WRITEABLE,
 	},
 	},
 	{
 	{
 		.name		= "kernel_ro",
 		.name		= "kernel_ro",
@@ -581,6 +583,10 @@ static int fsi_set_rate(int is_porta, int rate)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	switch (rate) {
 	switch (rate) {
+	case 44100:
+		clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000));
+		ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
+		break;
 	case 48000:
 	case 48000:
 		clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000));
 		clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000));
 		clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000));
 		clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000));

+ 1 - 1
arch/arm/mach-shmobile/intc-sh7372.c

@@ -98,7 +98,7 @@ static struct intc_vect intca_vectors[] __initdata = {
 	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
 	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
 	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
 	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
 	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
 	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
-	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ31A, 0x32a0),
+	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ21A, 0x32a0),
 	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
 	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
 	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
 	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
 	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
 	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),

+ 2 - 0
arch/arm/plat-omap/dma.c

@@ -1983,6 +1983,8 @@ static int omap2_dma_handle_ch(int ch)
 
 
 	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
 	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
 	dma_write(1 << ch, IRQSTATUS_L0);
 	dma_write(1 << ch, IRQSTATUS_L0);
+	/* read back the register to flush the write */
+	dma_read(IRQSTATUS_L0);
 
 
 	/* If the ch is not chained then chain_id will be -1 */
 	/* If the ch is not chained then chain_id will be -1 */
 	if (dma_chan[ch].chain_id != -1) {
 	if (dma_chan[ch].chain_id != -1) {

+ 83 - 20
arch/x86/pci/acpi.c

@@ -138,7 +138,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	struct acpi_resource_address64 addr;
 	struct acpi_resource_address64 addr;
 	acpi_status status;
 	acpi_status status;
 	unsigned long flags;
 	unsigned long flags;
-	struct resource *root, *conflict;
 	u64 start, end;
 	u64 start, end;
 
 
 	status = resource_to_addr(acpi_res, &addr);
 	status = resource_to_addr(acpi_res, &addr);
@@ -146,12 +145,10 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 		return AE_OK;
 		return AE_OK;
 
 
 	if (addr.resource_type == ACPI_MEMORY_RANGE) {
 	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		root = &iomem_resource;
 		flags = IORESOURCE_MEM;
 		flags = IORESOURCE_MEM;
 		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
 		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
 			flags |= IORESOURCE_PREFETCH;
 			flags |= IORESOURCE_PREFETCH;
 	} else if (addr.resource_type == ACPI_IO_RANGE) {
 	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		root = &ioport_resource;
 		flags = IORESOURCE_IO;
 		flags = IORESOURCE_IO;
 	} else
 	} else
 		return AE_OK;
 		return AE_OK;
@@ -172,25 +169,90 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 		return AE_OK;
 		return AE_OK;
 	}
 	}
 
 
-	conflict = insert_resource_conflict(root, res);
-	if (conflict) {
-		dev_err(&info->bridge->dev,
-			"address space collision: host bridge window %pR "
-			"conflicts with %s %pR\n",
-			res, conflict->name, conflict);
-	} else {
-		pci_bus_add_resource(info->bus, res, 0);
-		info->res_num++;
-		if (addr.translation_offset)
-			dev_info(&info->bridge->dev, "host bridge window %pR "
-				 "(PCI address [%#llx-%#llx])\n",
-				 res, res->start - addr.translation_offset,
-				 res->end - addr.translation_offset);
+	info->res_num++;
+	if (addr.translation_offset)
+		dev_info(&info->bridge->dev, "host bridge window %pR "
+			 "(PCI address [%#llx-%#llx])\n",
+			 res, res->start - addr.translation_offset,
+			 res->end - addr.translation_offset);
+	else
+		dev_info(&info->bridge->dev, "host bridge window %pR\n", res);
+
+	return AE_OK;
+}
+
+static bool resource_contains(struct resource *res, resource_size_t point)
+{
+	if (res->start <= point && point <= res->end)
+		return true;
+	return false;
+}
+
+static void coalesce_windows(struct pci_root_info *info, int type)
+{
+	int i, j;
+	struct resource *res1, *res2;
+
+	for (i = 0; i < info->res_num; i++) {
+		res1 = &info->res[i];
+		if (!(res1->flags & type))
+			continue;
+
+		for (j = i + 1; j < info->res_num; j++) {
+			res2 = &info->res[j];
+			if (!(res2->flags & type))
+				continue;
+
+			/*
+			 * I don't like throwing away windows because then
+			 * our resources no longer match the ACPI _CRS, but
+			 * the kernel resource tree doesn't allow overlaps.
+			 */
+			if (resource_contains(res1, res2->start) ||
+			    resource_contains(res1, res2->end) ||
+			    resource_contains(res2, res1->start) ||
+			    resource_contains(res2, res1->end)) {
+				res1->start = min(res1->start, res2->start);
+				res1->end = max(res1->end, res2->end);
+				dev_info(&info->bridge->dev,
+					 "host bridge window expanded to %pR; %pR ignored\n",
+					 res1, res2);
+				res2->flags = 0;
+			}
+		}
+	}
+}
+
+static void add_resources(struct pci_root_info *info)
+{
+	int i;
+	struct resource *res, *root, *conflict;
+
+	if (!pci_use_crs)
+		return;
+
+	coalesce_windows(info, IORESOURCE_MEM);
+	coalesce_windows(info, IORESOURCE_IO);
+
+	for (i = 0; i < info->res_num; i++) {
+		res = &info->res[i];
+
+		if (res->flags & IORESOURCE_MEM)
+			root = &iomem_resource;
+		else if (res->flags & IORESOURCE_IO)
+			root = &ioport_resource;
 		else
 		else
-			dev_info(&info->bridge->dev,
-				 "host bridge window %pR\n", res);
+			continue;
+
+		conflict = insert_resource_conflict(root, res);
+		if (conflict)
+			dev_err(&info->bridge->dev,
+				"address space collision: host bridge window %pR "
+				"conflicts with %s %pR\n",
+				res, conflict->name, conflict);
+		else
+			pci_bus_add_resource(info->bus, res, 0);
 	}
 	}
-	return AE_OK;
 }
 }
 
 
 static void
 static void
@@ -224,6 +286,7 @@ get_current_resources(struct acpi_device *device, int busnum,
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
 				&info);
 				&info);
 
 
+	add_resources(&info);
 	return;
 	return;
 
 
 name_alloc_fail:
 name_alloc_fail:

+ 0 - 4
block/blk-cgroup.c

@@ -1452,10 +1452,6 @@ blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup)
 		goto done;
 		goto done;
 	}
 	}
 
 
-	/* Currently we do not support hierarchy deeper than two level (0,1) */
-	if (parent != cgroup->top_cgroup)
-		return ERR_PTR(-EPERM);
-
 	blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
 	blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
 	if (!blkcg)
 	if (!blkcg)
 		return ERR_PTR(-ENOMEM);
 		return ERR_PTR(-ENOMEM);

+ 5 - 5
block/blk-core.c

@@ -33,7 +33,7 @@
 
 
 #include "blk.h"
 #include "blk.h"
 
 
-EXPORT_TRACEPOINT_SYMBOL_GPL(block_remap);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
 
 
@@ -1329,9 +1329,9 @@ static inline void blk_partition_remap(struct bio *bio)
 		bio->bi_sector += p->start_sect;
 		bio->bi_sector += p->start_sect;
 		bio->bi_bdev = bdev->bd_contains;
 		bio->bi_bdev = bdev->bd_contains;
 
 
-		trace_block_remap(bdev_get_queue(bio->bi_bdev), bio,
-				    bdev->bd_dev,
-				    bio->bi_sector - p->start_sect);
+		trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), bio,
+				      bdev->bd_dev,
+				      bio->bi_sector - p->start_sect);
 	}
 	}
 }
 }
 
 
@@ -1500,7 +1500,7 @@ static inline void __generic_make_request(struct bio *bio)
 			goto end_io;
 			goto end_io;
 
 
 		if (old_sector != -1)
 		if (old_sector != -1)
-			trace_block_remap(q, bio, old_dev, old_sector);
+			trace_block_bio_remap(q, bio, old_dev, old_sector);
 
 
 		old_sector = bio->bi_sector;
 		old_sector = bio->bi_sector;
 		old_dev = bio->bi_bdev->bd_dev;
 		old_dev = bio->bi_bdev->bd_dev;

+ 30 - 26
block/cfq-iosched.c

@@ -87,7 +87,6 @@ struct cfq_rb_root {
 	unsigned count;
 	unsigned count;
 	unsigned total_weight;
 	unsigned total_weight;
 	u64 min_vdisktime;
 	u64 min_vdisktime;
-	struct rb_node *active;
 };
 };
 #define CFQ_RB_ROOT	(struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
 #define CFQ_RB_ROOT	(struct cfq_rb_root) { .rb = RB_ROOT, .left = NULL, \
 			.count = 0, .min_vdisktime = 0, }
 			.count = 0, .min_vdisktime = 0, }
@@ -180,7 +179,6 @@ struct cfq_group {
 	/* group service_tree key */
 	/* group service_tree key */
 	u64 vdisktime;
 	u64 vdisktime;
 	unsigned int weight;
 	unsigned int weight;
-	bool on_st;
 
 
 	/* number of cfqq currently on this group */
 	/* number of cfqq currently on this group */
 	int nr_cfqq;
 	int nr_cfqq;
@@ -563,11 +561,6 @@ static void update_min_vdisktime(struct cfq_rb_root *st)
 	u64 vdisktime = st->min_vdisktime;
 	u64 vdisktime = st->min_vdisktime;
 	struct cfq_group *cfqg;
 	struct cfq_group *cfqg;
 
 
-	if (st->active) {
-		cfqg = rb_entry_cfqg(st->active);
-		vdisktime = cfqg->vdisktime;
-	}
-
 	if (st->left) {
 	if (st->left) {
 		cfqg = rb_entry_cfqg(st->left);
 		cfqg = rb_entry_cfqg(st->left);
 		vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime);
 		vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime);
@@ -646,11 +639,11 @@ cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 static inline bool cfq_slice_used(struct cfq_queue *cfqq)
 static inline bool cfq_slice_used(struct cfq_queue *cfqq)
 {
 {
 	if (cfq_cfqq_slice_new(cfqq))
 	if (cfq_cfqq_slice_new(cfqq))
-		return 0;
+		return false;
 	if (time_before(jiffies, cfqq->slice_end))
 	if (time_before(jiffies, cfqq->slice_end))
-		return 0;
+		return false;
 
 
-	return 1;
+	return true;
 }
 }
 
 
 /*
 /*
@@ -869,7 +862,7 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
 	struct rb_node *n;
 	struct rb_node *n;
 
 
 	cfqg->nr_cfqq++;
 	cfqg->nr_cfqq++;
-	if (cfqg->on_st)
+	if (!RB_EMPTY_NODE(&cfqg->rb_node))
 		return;
 		return;
 
 
 	/*
 	/*
@@ -885,7 +878,6 @@ cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
 		cfqg->vdisktime = st->min_vdisktime;
 		cfqg->vdisktime = st->min_vdisktime;
 
 
 	__cfq_group_service_tree_add(st, cfqg);
 	__cfq_group_service_tree_add(st, cfqg);
-	cfqg->on_st = true;
 	st->total_weight += cfqg->weight;
 	st->total_weight += cfqg->weight;
 }
 }
 
 
@@ -894,9 +886,6 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
 {
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
 
 
-	if (st->active == &cfqg->rb_node)
-		st->active = NULL;
-
 	BUG_ON(cfqg->nr_cfqq < 1);
 	BUG_ON(cfqg->nr_cfqq < 1);
 	cfqg->nr_cfqq--;
 	cfqg->nr_cfqq--;
 
 
@@ -905,7 +894,6 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
 		return;
 		return;
 
 
 	cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
 	cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
-	cfqg->on_st = false;
 	st->total_weight -= cfqg->weight;
 	st->total_weight -= cfqg->weight;
 	if (!RB_EMPTY_NODE(&cfqg->rb_node))
 	if (!RB_EMPTY_NODE(&cfqg->rb_node))
 		cfq_rb_erase(&cfqg->rb_node, st);
 		cfq_rb_erase(&cfqg->rb_node, st);
@@ -1095,7 +1083,7 @@ static void cfq_put_cfqg(struct cfq_group *cfqg)
 	if (!atomic_dec_and_test(&cfqg->ref))
 	if (!atomic_dec_and_test(&cfqg->ref))
 		return;
 		return;
 	for_each_cfqg_st(cfqg, i, j, st)
 	for_each_cfqg_st(cfqg, i, j, st)
-		BUG_ON(!RB_EMPTY_ROOT(&st->rb) || st->active != NULL);
+		BUG_ON(!RB_EMPTY_ROOT(&st->rb));
 	kfree(cfqg);
 	kfree(cfqg);
 }
 }
 
 
@@ -1687,9 +1675,6 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 	if (cfqq == cfqd->active_queue)
 	if (cfqq == cfqd->active_queue)
 		cfqd->active_queue = NULL;
 		cfqd->active_queue = NULL;
 
 
-	if (&cfqq->cfqg->rb_node == cfqd->grp_service_tree.active)
-		cfqd->grp_service_tree.active = NULL;
-
 	if (cfqd->active_cic) {
 	if (cfqd->active_cic) {
 		put_io_context(cfqd->active_cic->ioc);
 		put_io_context(cfqd->active_cic->ioc);
 		cfqd->active_cic = NULL;
 		cfqd->active_cic = NULL;
@@ -1901,10 +1886,10 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 	 * in their service tree.
 	 * in their service tree.
 	 */
 	 */
 	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
 	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq))
-		return 1;
+		return true;
 	cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
 	cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d",
 			service_tree->count);
 			service_tree->count);
-	return 0;
+	return false;
 }
 }
 
 
 static void cfq_arm_slice_timer(struct cfq_data *cfqd)
 static void cfq_arm_slice_timer(struct cfq_data *cfqd)
@@ -2116,6 +2101,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
 	unsigned count;
 	unsigned count;
 	struct cfq_rb_root *st;
 	struct cfq_rb_root *st;
 	unsigned group_slice;
 	unsigned group_slice;
+	enum wl_prio_t original_prio = cfqd->serving_prio;
 
 
 	if (!cfqg) {
 	if (!cfqg) {
 		cfqd->serving_prio = IDLE_WORKLOAD;
 		cfqd->serving_prio = IDLE_WORKLOAD;
@@ -2134,6 +2120,9 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
 		return;
 		return;
 	}
 	}
 
 
+	if (original_prio != cfqd->serving_prio)
+		goto new_workload;
+
 	/*
 	/*
 	 * For RT and BE, we have to choose also the type
 	 * For RT and BE, we have to choose also the type
 	 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
 	 * (SYNC, SYNC_NOIDLE, ASYNC), and to compute a workload
@@ -2148,6 +2137,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)
 	if (count && !time_after(jiffies, cfqd->workload_expires))
 	if (count && !time_after(jiffies, cfqd->workload_expires))
 		return;
 		return;
 
 
+new_workload:
 	/* otherwise select new workload type */
 	/* otherwise select new workload type */
 	cfqd->serving_type =
 	cfqd->serving_type =
 		cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
 		cfq_choose_wl(cfqd, cfqg, cfqd->serving_prio);
@@ -2199,7 +2189,6 @@ static struct cfq_group *cfq_get_next_cfqg(struct cfq_data *cfqd)
 	if (RB_EMPTY_ROOT(&st->rb))
 	if (RB_EMPTY_ROOT(&st->rb))
 		return NULL;
 		return NULL;
 	cfqg = cfq_rb_first_group(st);
 	cfqg = cfq_rb_first_group(st);
-	st->active = &cfqg->rb_node;
 	update_min_vdisktime(st);
 	update_min_vdisktime(st);
 	return cfqg;
 	return cfqg;
 }
 }
@@ -2293,6 +2282,17 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
 		goto keep_queue;
 		goto keep_queue;
 	}
 	}
 
 
+	/*
+	 * This is a deep seek queue, but the device is much faster than
+	 * the queue can deliver, don't idle
+	 **/
+	if (CFQQ_SEEKY(cfqq) && cfq_cfqq_idle_window(cfqq) &&
+	    (cfq_cfqq_slice_new(cfqq) ||
+	    (cfqq->slice_end - jiffies > jiffies - cfqq->slice_start))) {
+		cfq_clear_cfqq_deep(cfqq);
+		cfq_clear_cfqq_idle_window(cfqq);
+	}
+
 	if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
 	if (cfqq->dispatched && cfq_should_idle(cfqd, cfqq)) {
 		cfqq = NULL;
 		cfqq = NULL;
 		goto keep_queue;
 		goto keep_queue;
@@ -2367,12 +2367,12 @@ static inline bool cfq_slice_used_soon(struct cfq_data *cfqd,
 {
 {
 	/* the queue hasn't finished any request, can't estimate */
 	/* the queue hasn't finished any request, can't estimate */
 	if (cfq_cfqq_slice_new(cfqq))
 	if (cfq_cfqq_slice_new(cfqq))
-		return 1;
+		return true;
 	if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched,
 	if (time_after(jiffies + cfqd->cfq_slice_idle * cfqq->dispatched,
 		cfqq->slice_end))
 		cfqq->slice_end))
-		return 1;
+		return true;
 
 
-	return 0;
+	return false;
 }
 }
 
 
 static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 static bool cfq_may_dispatch(struct cfq_data *cfqd, struct cfq_queue *cfqq)
@@ -3265,6 +3265,10 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
 	if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
 	if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
 		return true;
 		return true;
 
 
+	/* An idle queue should not be idle now for some reason */
+	if (RB_EMPTY_ROOT(&cfqq->sort_list) && !cfq_should_idle(cfqd, cfqq))
+		return true;
+
 	if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
 	if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
 		return false;
 		return false;
 
 

+ 3 - 2
block/ioctl.c

@@ -295,11 +295,12 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 			return -EINVAL;
 			return -EINVAL;
 		if (get_user(n, (int __user *) arg))
 		if (get_user(n, (int __user *) arg))
 			return -EFAULT;
 			return -EFAULT;
-		if (!(mode & FMODE_EXCL) && bd_claim(bdev, &bdev) < 0)
+		if (!(mode & FMODE_EXCL) &&
+		    blkdev_get(bdev, mode | FMODE_EXCL, &bdev) < 0)
 			return -EBUSY;
 			return -EBUSY;
 		ret = set_blocksize(bdev, n);
 		ret = set_blocksize(bdev, n);
 		if (!(mode & FMODE_EXCL))
 		if (!(mode & FMODE_EXCL))
-			bd_release(bdev);
+			blkdev_put(bdev, mode | FMODE_EXCL);
 		return ret;
 		return ret;
 	case BLKPG:
 	case BLKPG:
 		ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
 		ret = blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);

+ 0 - 2
drivers/block/drbd/drbd_int.h

@@ -911,8 +911,6 @@ struct drbd_md {
 struct drbd_backing_dev {
 struct drbd_backing_dev {
 	struct block_device *backing_bdev;
 	struct block_device *backing_bdev;
 	struct block_device *md_bdev;
 	struct block_device *md_bdev;
-	struct file *lo_file;
-	struct file *md_file;
 	struct drbd_md md;
 	struct drbd_md md;
 	struct disk_conf dc; /* The user provided config... */
 	struct disk_conf dc; /* The user provided config... */
 	sector_t known_size; /* last known size of that backing device */
 	sector_t known_size; /* last known size of that backing device */

+ 2 - 5
drivers/block/drbd/drbd_main.c

@@ -3372,11 +3372,8 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
 	if (ldev == NULL)
 	if (ldev == NULL)
 		return;
 		return;
 
 
-	bd_release(ldev->backing_bdev);
-	bd_release(ldev->md_bdev);
-
-	fput(ldev->lo_file);
-	fput(ldev->md_file);
+	blkdev_put(ldev->backing_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+	blkdev_put(ldev->md_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 
 
 	kfree(ldev);
 	kfree(ldev);
 }
 }

+ 36 - 67
drivers/block/drbd/drbd_nl.c

@@ -855,7 +855,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	sector_t max_possible_sectors;
 	sector_t max_possible_sectors;
 	sector_t min_md_device_sectors;
 	sector_t min_md_device_sectors;
 	struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
 	struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
-	struct inode *inode, *inode2;
+	struct block_device *bdev;
 	struct lru_cache *resync_lru = NULL;
 	struct lru_cache *resync_lru = NULL;
 	union drbd_state ns, os;
 	union drbd_state ns, os;
 	unsigned int max_seg_s;
 	unsigned int max_seg_s;
@@ -907,46 +907,40 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 		}
 		}
 	}
 	}
 
 
-	nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0);
-	if (IS_ERR(nbc->lo_file)) {
+	bdev = blkdev_get_by_path(nbc->dc.backing_dev,
+				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev);
+	if (IS_ERR(bdev)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
-		    PTR_ERR(nbc->lo_file));
-		nbc->lo_file = NULL;
+			PTR_ERR(bdev));
 		retcode = ERR_OPEN_DISK;
 		retcode = ERR_OPEN_DISK;
 		goto fail;
 		goto fail;
 	}
 	}
+	nbc->backing_bdev = bdev;
 
 
-	inode = nbc->lo_file->f_dentry->d_inode;
-
-	if (!S_ISBLK(inode->i_mode)) {
-		retcode = ERR_DISK_NOT_BDEV;
-		goto fail;
-	}
-
-	nbc->md_file = filp_open(nbc->dc.meta_dev, O_RDWR, 0);
-	if (IS_ERR(nbc->md_file)) {
+	/*
+	 * meta_dev_idx >= 0: external fixed size, possibly multiple
+	 * drbd sharing one meta device.  TODO in that case, paranoia
+	 * check that [md_bdev, meta_dev_idx] is not yet used by some
+	 * other drbd minor!  (if you use drbd.conf + drbdadm, that
+	 * should check it for you already; but if you don't, or
+	 * someone fooled it, we need to double check here)
+	 */
+	bdev = blkdev_get_by_path(nbc->dc.meta_dev,
+				  FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+				  (nbc->dc.meta_dev_idx < 0) ?
+				  (void *)mdev : (void *)drbd_m_holder);
+	if (IS_ERR(bdev)) {
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev,
 		dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev,
-		    PTR_ERR(nbc->md_file));
-		nbc->md_file = NULL;
+			PTR_ERR(bdev));
 		retcode = ERR_OPEN_MD_DISK;
 		retcode = ERR_OPEN_MD_DISK;
 		goto fail;
 		goto fail;
 	}
 	}
+	nbc->md_bdev = bdev;
 
 
-	inode2 = nbc->md_file->f_dentry->d_inode;
-
-	if (!S_ISBLK(inode2->i_mode)) {
-		retcode = ERR_MD_NOT_BDEV;
-		goto fail;
-	}
-
-	nbc->backing_bdev = inode->i_bdev;
-	if (bd_claim(nbc->backing_bdev, mdev)) {
-		printk(KERN_ERR "drbd: bd_claim(%p,%p); failed [%p;%p;%u]\n",
-		       nbc->backing_bdev, mdev,
-		       nbc->backing_bdev->bd_holder,
-		       nbc->backing_bdev->bd_contains->bd_holder,
-		       nbc->backing_bdev->bd_holders);
-		retcode = ERR_BDCLAIM_DISK;
+	if ((nbc->backing_bdev == nbc->md_bdev) !=
+	    (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
+	     nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
+		retcode = ERR_MD_IDX_INVALID;
 		goto fail;
 		goto fail;
 	}
 	}
 
 
@@ -955,28 +949,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 			offsetof(struct bm_extent, lce));
 			offsetof(struct bm_extent, lce));
 	if (!resync_lru) {
 	if (!resync_lru) {
 		retcode = ERR_NOMEM;
 		retcode = ERR_NOMEM;
-		goto release_bdev_fail;
-	}
-
-	/* meta_dev_idx >= 0: external fixed size,
-	 * possibly multiple drbd sharing one meta device.
-	 * TODO in that case, paranoia check that [md_bdev, meta_dev_idx] is
-	 * not yet used by some other drbd minor!
-	 * (if you use drbd.conf + drbdadm,
-	 * that should check it for you already; but if you don't, or someone
-	 * fooled it, we need to double check here) */
-	nbc->md_bdev = inode2->i_bdev;
-	if (bd_claim(nbc->md_bdev, (nbc->dc.meta_dev_idx < 0) ? (void *)mdev
-				: (void *) drbd_m_holder)) {
-		retcode = ERR_BDCLAIM_MD_DISK;
-		goto release_bdev_fail;
-	}
-
-	if ((nbc->backing_bdev == nbc->md_bdev) !=
-	    (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
-	     nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
-		retcode = ERR_MD_IDX_INVALID;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 	}
 
 
 	/* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
 	/* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
@@ -987,7 +960,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 			(unsigned long long) drbd_get_max_capacity(nbc),
 			(unsigned long long) drbd_get_max_capacity(nbc),
 			(unsigned long long) nbc->dc.disk_size);
 			(unsigned long long) nbc->dc.disk_size);
 		retcode = ERR_DISK_TO_SMALL;
 		retcode = ERR_DISK_TO_SMALL;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 	}
 
 
 	if (nbc->dc.meta_dev_idx < 0) {
 	if (nbc->dc.meta_dev_idx < 0) {
@@ -1004,7 +977,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 		dev_warn(DEV, "refusing attach: md-device too small, "
 		dev_warn(DEV, "refusing attach: md-device too small, "
 		     "at least %llu sectors needed for this meta-disk type\n",
 		     "at least %llu sectors needed for this meta-disk type\n",
 		     (unsigned long long) min_md_device_sectors);
 		     (unsigned long long) min_md_device_sectors);
-		goto release_bdev2_fail;
+		goto fail;
 	}
 	}
 
 
 	/* Make sure the new disk is big enough
 	/* Make sure the new disk is big enough
@@ -1012,7 +985,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	if (drbd_get_max_capacity(nbc) <
 	if (drbd_get_max_capacity(nbc) <
 	    drbd_get_capacity(mdev->this_bdev)) {
 	    drbd_get_capacity(mdev->this_bdev)) {
 		retcode = ERR_DISK_TO_SMALL;
 		retcode = ERR_DISK_TO_SMALL;
-		goto release_bdev2_fail;
+		goto fail;
 	}
 	}
 
 
 	nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
 	nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
@@ -1035,7 +1008,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
 	retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
 	retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
 	drbd_resume_io(mdev);
 	drbd_resume_io(mdev);
 	if (retcode < SS_SUCCESS)
 	if (retcode < SS_SUCCESS)
-		goto release_bdev2_fail;
+		goto fail;
 
 
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
 		goto force_diskless;
 		goto force_diskless;
@@ -1269,18 +1242,14 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
  force_diskless:
  force_diskless:
 	drbd_force_state(mdev, NS(disk, D_FAILED));
 	drbd_force_state(mdev, NS(disk, D_FAILED));
 	drbd_md_sync(mdev);
 	drbd_md_sync(mdev);
- release_bdev2_fail:
-	if (nbc)
-		bd_release(nbc->md_bdev);
- release_bdev_fail:
-	if (nbc)
-		bd_release(nbc->backing_bdev);
  fail:
  fail:
 	if (nbc) {
 	if (nbc) {
-		if (nbc->lo_file)
-			fput(nbc->lo_file);
-		if (nbc->md_file)
-			fput(nbc->md_file);
+		if (nbc->backing_bdev)
+			blkdev_put(nbc->backing_bdev,
+				   FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+		if (nbc->md_bdev)
+			blkdev_put(nbc->md_bdev,
+				   FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 		kfree(nbc);
 		kfree(nbc);
 	}
 	}
 	lc_destroy(resync_lru);
 	lc_destroy(resync_lru);

+ 8 - 14
drivers/block/pktcdvd.c

@@ -2296,15 +2296,12 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 	 * so bdget() can't fail.
 	 * so bdget() can't fail.
 	 */
 	 */
 	bdget(pd->bdev->bd_dev);
 	bdget(pd->bdev->bd_dev);
-	if ((ret = blkdev_get(pd->bdev, FMODE_READ)))
+	if ((ret = blkdev_get(pd->bdev, FMODE_READ | FMODE_EXCL, pd)))
 		goto out;
 		goto out;
 
 
-	if ((ret = bd_claim(pd->bdev, pd)))
-		goto out_putdev;
-
 	if ((ret = pkt_get_last_written(pd, &lba))) {
 	if ((ret = pkt_get_last_written(pd, &lba))) {
 		printk(DRIVER_NAME": pkt_get_last_written failed\n");
 		printk(DRIVER_NAME": pkt_get_last_written failed\n");
-		goto out_unclaim;
+		goto out_putdev;
 	}
 	}
 
 
 	set_capacity(pd->disk, lba << 2);
 	set_capacity(pd->disk, lba << 2);
@@ -2314,7 +2311,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 	q = bdev_get_queue(pd->bdev);
 	q = bdev_get_queue(pd->bdev);
 	if (write) {
 	if (write) {
 		if ((ret = pkt_open_write(pd)))
 		if ((ret = pkt_open_write(pd)))
-			goto out_unclaim;
+			goto out_putdev;
 		/*
 		/*
 		 * Some CDRW drives can not handle writes larger than one packet,
 		 * Some CDRW drives can not handle writes larger than one packet,
 		 * even if the size is a multiple of the packet size.
 		 * even if the size is a multiple of the packet size.
@@ -2329,23 +2326,21 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
 	}
 	}
 
 
 	if ((ret = pkt_set_segment_merging(pd, q)))
 	if ((ret = pkt_set_segment_merging(pd, q)))
-		goto out_unclaim;
+		goto out_putdev;
 
 
 	if (write) {
 	if (write) {
 		if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
 		if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
 			printk(DRIVER_NAME": not enough memory for buffers\n");
 			printk(DRIVER_NAME": not enough memory for buffers\n");
 			ret = -ENOMEM;
 			ret = -ENOMEM;
-			goto out_unclaim;
+			goto out_putdev;
 		}
 		}
 		printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
 		printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
 	}
 	}
 
 
 	return 0;
 	return 0;
 
 
-out_unclaim:
-	bd_release(pd->bdev);
 out_putdev:
 out_putdev:
-	blkdev_put(pd->bdev, FMODE_READ);
+	blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
 out:
 out:
 	return ret;
 	return ret;
 }
 }
@@ -2362,8 +2357,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
 	pkt_lock_door(pd, 0);
 	pkt_lock_door(pd, 0);
 
 
 	pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
 	pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
-	bd_release(pd->bdev);
-	blkdev_put(pd->bdev, FMODE_READ);
+	blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
 
 
 	pkt_shrink_pktlist(pd);
 	pkt_shrink_pktlist(pd);
 }
 }
@@ -2733,7 +2727,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
 	bdev = bdget(dev);
 	bdev = bdget(dev);
 	if (!bdev)
 	if (!bdev)
 		return -ENOMEM;
 		return -ENOMEM;
-	ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY);
+	ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 

+ 4 - 4
drivers/char/i8k.c

@@ -120,7 +120,7 @@ static int i8k_smm(struct smm_regs *regs)
 	int eax = regs->eax;
 	int eax = regs->eax;
 
 
 #if defined(CONFIG_X86_64)
 #if defined(CONFIG_X86_64)
-	asm("pushq %%rax\n\t"
+	asm volatile("pushq %%rax\n\t"
 		"movl 0(%%rax),%%edx\n\t"
 		"movl 0(%%rax),%%edx\n\t"
 		"pushq %%rdx\n\t"
 		"pushq %%rdx\n\t"
 		"movl 4(%%rax),%%ebx\n\t"
 		"movl 4(%%rax),%%ebx\n\t"
@@ -142,11 +142,11 @@ static int i8k_smm(struct smm_regs *regs)
 		"lahf\n\t"
 		"lahf\n\t"
 		"shrl $8,%%eax\n\t"
 		"shrl $8,%%eax\n\t"
 		"andl $1,%%eax\n"
 		"andl $1,%%eax\n"
-		:"=a"(rc), "+m" (*regs)
+		:"=a"(rc)
 		:    "a"(regs)
 		:    "a"(regs)
 		:    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 		:    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 #else
 #else
-	asm("pushl %%eax\n\t"
+	asm volatile("pushl %%eax\n\t"
 	    "movl 0(%%eax),%%edx\n\t"
 	    "movl 0(%%eax),%%edx\n\t"
 	    "push %%edx\n\t"
 	    "push %%edx\n\t"
 	    "movl 4(%%eax),%%ebx\n\t"
 	    "movl 4(%%eax),%%ebx\n\t"
@@ -168,7 +168,7 @@ static int i8k_smm(struct smm_regs *regs)
 	    "lahf\n\t"
 	    "lahf\n\t"
 	    "shrl $8,%%eax\n\t"
 	    "shrl $8,%%eax\n\t"
 	    "andl $1,%%eax\n"
 	    "andl $1,%%eax\n"
-	    :"=a"(rc), "+m" (*regs)
+	    :"=a"(rc)
 	    :    "a"(regs)
 	    :    "a"(regs)
 	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 #endif
 #endif

+ 4 - 10
drivers/char/raw.c

@@ -65,15 +65,12 @@ static int raw_open(struct inode *inode, struct file *filp)
 	if (!bdev)
 	if (!bdev)
 		goto out;
 		goto out;
 	igrab(bdev->bd_inode);
 	igrab(bdev->bd_inode);
-	err = blkdev_get(bdev, filp->f_mode);
+	err = blkdev_get(bdev, filp->f_mode | FMODE_EXCL, raw_open);
 	if (err)
 	if (err)
 		goto out;
 		goto out;
-	err = bd_claim(bdev, raw_open);
-	if (err)
-		goto out1;
 	err = set_blocksize(bdev, bdev_logical_block_size(bdev));
 	err = set_blocksize(bdev, bdev_logical_block_size(bdev));
 	if (err)
 	if (err)
-		goto out2;
+		goto out1;
 	filp->f_flags |= O_DIRECT;
 	filp->f_flags |= O_DIRECT;
 	filp->f_mapping = bdev->bd_inode->i_mapping;
 	filp->f_mapping = bdev->bd_inode->i_mapping;
 	if (++raw_devices[minor].inuse == 1)
 	if (++raw_devices[minor].inuse == 1)
@@ -83,10 +80,8 @@ static int raw_open(struct inode *inode, struct file *filp)
 	mutex_unlock(&raw_mutex);
 	mutex_unlock(&raw_mutex);
 	return 0;
 	return 0;
 
 
-out2:
-	bd_release(bdev);
 out1:
 out1:
-	blkdev_put(bdev, filp->f_mode);
+	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
 out:
 out:
 	mutex_unlock(&raw_mutex);
 	mutex_unlock(&raw_mutex);
 	return err;
 	return err;
@@ -110,8 +105,7 @@ static int raw_release(struct inode *inode, struct file *filp)
 	}
 	}
 	mutex_unlock(&raw_mutex);
 	mutex_unlock(&raw_mutex);
 
 
-	bd_release(bdev);
-	blkdev_put(bdev, filp->f_mode);
+	blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 1
drivers/hwmon/amc6821.c

@@ -4,7 +4,7 @@
 	Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
 	Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
 
 
 	Based on max6650.c:
 	Based on max6650.c:
-	Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de>
+	Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
 	it under the terms of the GNU General Public License as published by
 	it under the terms of the GNU General Public License as published by

+ 2 - 2
drivers/hwmon/lm93.c

@@ -20,7 +20,7 @@
     Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org>
     Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org>
         Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab
         Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab
 
 
-    Modified for mainline integration by Hans J. Koch <hjk@linutronix.de>
+    Modified for mainline integration by Hans J. Koch <hjk@hansjkoch.de>
         Copyright (c) 2007 Hans J. Koch, Linutronix GmbH
         Copyright (c) 2007 Hans J. Koch, Linutronix GmbH
 
 
     This program is free software; you can redistribute it and/or modify
     This program is free software; you can redistribute it and/or modify
@@ -2629,7 +2629,7 @@ static void __exit lm93_exit(void)
 }
 }
 
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, "
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, "
-		"Hans J. Koch <hjk@linutronix.de");
+		"Hans J. Koch <hjk@hansjkoch.de>");
 MODULE_DESCRIPTION("LM93 driver");
 MODULE_DESCRIPTION("LM93 driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 

+ 14 - 5
drivers/hwmon/lm95241.c

@@ -128,9 +128,12 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
 {
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm95241_data *data = i2c_get_clientdata(client);
 	struct lm95241_data *data = i2c_get_clientdata(client);
+	unsigned long val;
 
 
-	strict_strtol(buf, 10, &data->interval);
-	data->interval = data->interval * HZ / 1000;
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	data->interval = val * HZ / 1000;
 
 
 	return count;
 	return count;
 }
 }
@@ -188,7 +191,9 @@ static ssize_t set_type##flag(struct device *dev, \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 \
 \
 	long val; \
 	long val; \
-	strict_strtol(buf, 10, &val); \
+\
+	if (strict_strtol(buf, 10, &val) < 0) \
+		return -EINVAL; \
 \
 \
 	if ((val == 1) || (val == 2)) { \
 	if ((val == 1) || (val == 2)) { \
 \
 \
@@ -227,7 +232,9 @@ static ssize_t set_min##flag(struct device *dev, \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 \
 \
 	long val; \
 	long val; \
-	strict_strtol(buf, 10, &val); \
+\
+	if (strict_strtol(buf, 10, &val) < 0) \
+		return -EINVAL;\
 \
 \
 	mutex_lock(&data->update_lock); \
 	mutex_lock(&data->update_lock); \
 \
 \
@@ -256,7 +263,9 @@ static ssize_t set_max##flag(struct device *dev, \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 	struct lm95241_data *data = i2c_get_clientdata(client); \
 \
 \
 	long val; \
 	long val; \
-	strict_strtol(buf, 10, &val); \
+\
+	if (strict_strtol(buf, 10, &val) < 0) \
+		return -EINVAL; \
 \
 \
 	mutex_lock(&data->update_lock); \
 	mutex_lock(&data->update_lock); \
 \
 \

+ 1 - 1
drivers/hwmon/max6650.c

@@ -2,7 +2,7 @@
  * max6650.c - Part of lm_sensors, Linux kernel modules for hardware
  * max6650.c - Part of lm_sensors, Linux kernel modules for hardware
  *             monitoring.
  *             monitoring.
  *
  *
- * (C) 2007 by Hans J. Koch <hjk@linutronix.de>
+ * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
  *
  *
  * based on code written by John Morris <john.morris@spirentcom.com>
  * based on code written by John Morris <john.morris@spirentcom.com>
  * Copyright (c) 2003 Spirent Communications
  * Copyright (c) 2003 Spirent Communications

+ 174 - 33
drivers/hwmon/w83795.c

@@ -165,10 +165,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
 
 
 #define W83795_REG_VID_CTRL		0x6A
 #define W83795_REG_VID_CTRL		0x6A
 
 
+#define W83795_REG_ALARM_CTRL		0x40
+#define ALARM_CTRL_RTSACS		(1 << 7)
 #define W83795_REG_ALARM(index)		(0x41 + (index))
 #define W83795_REG_ALARM(index)		(0x41 + (index))
+#define W83795_REG_CLR_CHASSIS		0x4D
 #define W83795_REG_BEEP(index)		(0x50 + (index))
 #define W83795_REG_BEEP(index)		(0x50 + (index))
 
 
-#define W83795_REG_CLR_CHASSIS		0x4D
+#define W83795_REG_OVT_CFG		0x58
+#define OVT_CFG_SEL			(1 << 7)
 
 
 
 
 #define W83795_REG_FCMS1		0x201
 #define W83795_REG_FCMS1		0x201
@@ -178,6 +182,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
 
 
 #define W83795_REG_TSS(index)		(0x209 + (index))
 #define W83795_REG_TSS(index)		(0x209 + (index))
 
 
+#define TSS_MAP_RESERVED		0xff
+static const u8 tss_map[4][6] = {
+	{ 0,  1,  2,  3,  4,  5},
+	{ 6,  7,  8,  9,  0,  1},
+	{10, 11, 12, 13,  2,  3},
+	{ 4,  5,  4,  5, TSS_MAP_RESERVED, TSS_MAP_RESERVED},
+};
+
 #define PWM_OUTPUT			0
 #define PWM_OUTPUT			0
 #define PWM_FREQ			1
 #define PWM_FREQ			1
 #define PWM_START			2
 #define PWM_START			2
@@ -369,6 +381,7 @@ struct w83795_data {
 	u8 setup_pwm[3];	/* Register value */
 	u8 setup_pwm[3];	/* Register value */
 
 
 	u8 alarms[6];		/* Register value */
 	u8 alarms[6];		/* Register value */
+	u8 enable_beep;
 	u8 beeps[6];		/* Register value */
 	u8 beeps[6];		/* Register value */
 
 
 	char valid;
 	char valid;
@@ -499,8 +512,11 @@ static void w83795_update_limits(struct i2c_client *client)
 	}
 	}
 
 
 	/* Read beep settings */
 	/* Read beep settings */
-	for (i = 0; i < ARRAY_SIZE(data->beeps); i++)
-		data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i));
+	if (data->enable_beep) {
+		for (i = 0; i < ARRAY_SIZE(data->beeps); i++)
+			data->beeps[i] =
+				w83795_read(client, W83795_REG_BEEP(i));
+	}
 
 
 	data->valid_limits = 1;
 	data->valid_limits = 1;
 }
 }
@@ -577,6 +593,7 @@ static struct w83795_data *w83795_update_device(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83795_data *data = i2c_get_clientdata(client);
 	struct w83795_data *data = i2c_get_clientdata(client);
 	u16 tmp;
 	u16 tmp;
+	u8 intrusion;
 	int i;
 	int i;
 
 
 	mutex_lock(&data->update_lock);
 	mutex_lock(&data->update_lock);
@@ -648,9 +665,24 @@ static struct w83795_data *w83795_update_device(struct device *dev)
 		    w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT));
 		    w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT));
 	}
 	}
 
 
-	/* update alarm */
+	/* Update intrusion and alarms
+	 * It is important to read intrusion first, because reading from
+	 * register SMI STS6 clears the interrupt status temporarily. */
+	tmp = w83795_read(client, W83795_REG_ALARM_CTRL);
+	/* Switch to interrupt status for intrusion if needed */
+	if (tmp & ALARM_CTRL_RTSACS)
+		w83795_write(client, W83795_REG_ALARM_CTRL,
+			     tmp & ~ALARM_CTRL_RTSACS);
+	intrusion = w83795_read(client, W83795_REG_ALARM(5)) & (1 << 6);
+	/* Switch to real-time alarms */
+	w83795_write(client, W83795_REG_ALARM_CTRL, tmp | ALARM_CTRL_RTSACS);
 	for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
 	for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
 		data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
 		data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
+	data->alarms[5] |= intrusion;
+	/* Restore original configuration if needed */
+	if (!(tmp & ALARM_CTRL_RTSACS))
+		w83795_write(client, W83795_REG_ALARM_CTRL,
+			     tmp & ~ALARM_CTRL_RTSACS);
 
 
 	data->last_updated = jiffies;
 	data->last_updated = jiffies;
 	data->valid = 1;
 	data->valid = 1;
@@ -730,6 +762,10 @@ store_chassis_clear(struct device *dev,
 	val = w83795_read(client, W83795_REG_CLR_CHASSIS);
 	val = w83795_read(client, W83795_REG_CLR_CHASSIS);
 	val |= 0x80;
 	val |= 0x80;
 	w83795_write(client, W83795_REG_CLR_CHASSIS, val);
 	w83795_write(client, W83795_REG_CLR_CHASSIS, val);
+
+	/* Clear status and force cache refresh */
+	w83795_read(client, W83795_REG_ALARM(5));
+	data->valid = 0;
 	mutex_unlock(&data->update_lock);
 	mutex_unlock(&data->update_lock);
 	return count;
 	return count;
 }
 }
@@ -857,20 +893,20 @@ show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
 	int index = sensor_attr->index;
 	int index = sensor_attr->index;
 	u8 tmp;
 	u8 tmp;
 
 
-	if (1 == (data->pwm_fcms[0] & (1 << index))) {
+	/* Speed cruise mode */
+	if (data->pwm_fcms[0] & (1 << index)) {
 		tmp = 2;
 		tmp = 2;
 		goto out;
 		goto out;
 	}
 	}
+	/* Thermal cruise or SmartFan IV mode */
 	for (tmp = 0; tmp < 6; tmp++) {
 	for (tmp = 0; tmp < 6; tmp++) {
 		if (data->pwm_tfmr[tmp] & (1 << index)) {
 		if (data->pwm_tfmr[tmp] & (1 << index)) {
 			tmp = 3;
 			tmp = 3;
 			goto out;
 			goto out;
 		}
 		}
 	}
 	}
-	if (data->pwm_fomc & (1 << index))
-		tmp = 0;
-	else
-		tmp = 1;
+	/* Manual mode */
+	tmp = 1;
 
 
 out:
 out:
 	return sprintf(buf, "%u\n", tmp);
 	return sprintf(buf, "%u\n", tmp);
@@ -890,23 +926,21 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 
 
 	if (strict_strtoul(buf, 10, &val) < 0)
 	if (strict_strtoul(buf, 10, &val) < 0)
 		return -EINVAL;
 		return -EINVAL;
-	if (val > 2)
+	if (val < 1 || val > 2)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	mutex_lock(&data->update_lock);
 	mutex_lock(&data->update_lock);
 	switch (val) {
 	switch (val) {
-	case 0:
 	case 1:
 	case 1:
+		/* Clear speed cruise mode bits */
 		data->pwm_fcms[0] &= ~(1 << index);
 		data->pwm_fcms[0] &= ~(1 << index);
 		w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]);
 		w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]);
+		/* Clear thermal cruise mode bits */
 		for (i = 0; i < 6; i++) {
 		for (i = 0; i < 6; i++) {
 			data->pwm_tfmr[i] &= ~(1 << index);
 			data->pwm_tfmr[i] &= ~(1 << index);
 			w83795_write(client, W83795_REG_TFMR(i),
 			w83795_write(client, W83795_REG_TFMR(i),
 				data->pwm_tfmr[i]);
 				data->pwm_tfmr[i]);
 		}
 		}
-		data->pwm_fomc |= 1 << index;
-		data->pwm_fomc ^= val << index;
-		w83795_write(client, W83795_REG_FOMC, data->pwm_fomc);
 		break;
 		break;
 	case 2:
 	case 2:
 		data->pwm_fcms[0] |= (1 << index);
 		data->pwm_fcms[0] |= (1 << index);
@@ -917,6 +951,42 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 	return count;
 	return count;
 }
 }
 
 
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83795_data *data = w83795_update_pwm_config(dev);
+	int index = to_sensor_dev_attr_2(attr)->index;
+	unsigned int mode;
+
+	if (data->pwm_fomc & (1 << index))
+		mode = 0;	/* DC */
+	else
+		mode = 1;	/* PWM */
+
+	return sprintf(buf, "%u\n", mode);
+}
+
+/*
+ * Check whether a given temperature source can ever be useful.
+ * Returns the number of selectable temperature channels which are
+ * enabled.
+ */
+static int w83795_tss_useful(const struct w83795_data *data, int tsrc)
+{
+	int useful = 0, i;
+
+	for (i = 0; i < 4; i++) {
+		if (tss_map[i][tsrc] == TSS_MAP_RESERVED)
+			continue;
+		if (tss_map[i][tsrc] < 6)	/* Analog */
+			useful += (data->has_temp >> tss_map[i][tsrc]) & 1;
+		else				/* Digital */
+			useful += (data->has_dts >> (tss_map[i][tsrc] - 6)) & 1;
+	}
+
+	return useful;
+}
+
 static ssize_t
 static ssize_t
 show_temp_src(struct device *dev, struct device_attribute *attr, char *buf)
 show_temp_src(struct device *dev, struct device_attribute *attr, char *buf)
 {
 {
@@ -924,17 +994,18 @@ show_temp_src(struct device *dev, struct device_attribute *attr, char *buf)
 	    to_sensor_dev_attr_2(attr);
 	    to_sensor_dev_attr_2(attr);
 	struct w83795_data *data = w83795_update_pwm_config(dev);
 	struct w83795_data *data = w83795_update_pwm_config(dev);
 	int index = sensor_attr->index;
 	int index = sensor_attr->index;
-	u8 val = index / 2;
-	u8 tmp = data->temp_src[val];
+	u8 tmp = data->temp_src[index / 2];
 
 
 	if (index & 1)
 	if (index & 1)
-		val = 4;
+		tmp >>= 4;	/* Pick high nibble */
 	else
 	else
-		val = 0;
-	tmp >>= val;
-	tmp &= 0x0f;
+		tmp &= 0x0f;	/* Pick low nibble */
 
 
-	return sprintf(buf, "%u\n", tmp);
+	/* Look-up the actual temperature channel number */
+	if (tmp >= 4 || tss_map[tmp][index] == TSS_MAP_RESERVED)
+		return -EINVAL;		/* Shouldn't happen */
+
+	return sprintf(buf, "%u\n", (unsigned int)tss_map[tmp][index] + 1);
 }
 }
 
 
 static ssize_t
 static ssize_t
@@ -946,12 +1017,21 @@ store_temp_src(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute_2 *sensor_attr =
 	struct sensor_device_attribute_2 *sensor_attr =
 	    to_sensor_dev_attr_2(attr);
 	    to_sensor_dev_attr_2(attr);
 	int index = sensor_attr->index;
 	int index = sensor_attr->index;
-	unsigned long tmp;
+	int tmp;
+	unsigned long channel;
 	u8 val = index / 2;
 	u8 val = index / 2;
 
 
-	if (strict_strtoul(buf, 10, &tmp) < 0)
+	if (strict_strtoul(buf, 10, &channel) < 0 ||
+	    channel < 1 || channel > 14)
+		return -EINVAL;
+
+	/* Check if request can be fulfilled */
+	for (tmp = 0; tmp < 4; tmp++) {
+		if (tss_map[tmp][index] == channel - 1)
+			break;
+	}
+	if (tmp == 4)	/* No match */
 		return -EINVAL;
 		return -EINVAL;
-	tmp = SENSORS_LIMIT(tmp, 0, 15);
 
 
 	mutex_lock(&data->update_lock);
 	mutex_lock(&data->update_lock);
 	if (index & 1) {
 	if (index & 1) {
@@ -1515,7 +1595,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 
 
 #define NOT_USED			-1
 #define NOT_USED			-1
 
 
-/* Don't change the attribute order, _max and _min are accessed by index
+/* Don't change the attribute order, _max, _min and _beep are accessed by index
  * somewhere else in the code */
  * somewhere else in the code */
 #define SENSOR_ATTR_IN(index) {						\
 #define SENSOR_ATTR_IN(index) {						\
 	SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL,	\
 	SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL,	\
@@ -1530,6 +1610,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 		show_alarm_beep, store_beep, BEEP_ENABLE,		\
 		show_alarm_beep, store_beep, BEEP_ENABLE,		\
 		index + ((index > 14) ? 1 : 0)) }
 		index + ((index > 14) ? 1 : 0)) }
 
 
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
 #define SENSOR_ATTR_FAN(index) {					\
 #define SENSOR_ATTR_FAN(index) {					\
 	SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan,		\
 	SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan,		\
 		NULL, FAN_INPUT, index - 1), \
 		NULL, FAN_INPUT, index - 1), \
@@ -1553,9 +1635,13 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 		show_pwm, store_pwm, PWM_FREQ, index - 1),	 \
 		show_pwm, store_pwm, PWM_FREQ, index - 1),	 \
 	SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO,		\
 	SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO,		\
 		show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \
 		show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \
+	SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO,			\
+		show_pwm_mode, NULL, NOT_USED, index - 1),		\
 	SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \
 	SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \
 		show_fanin, store_fanin, FANIN_TARGET, index - 1) }
 		show_fanin, store_fanin, FANIN_TARGET, index - 1) }
 
 
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
 #define SENSOR_ATTR_DTS(index) {					\
 #define SENSOR_ATTR_DTS(index) {					\
 	SENSOR_ATTR_2(temp##index##_type, S_IRUGO ,		\
 	SENSOR_ATTR_2(temp##index##_type, S_IRUGO ,		\
 		show_dts_mode, NULL, NOT_USED, index - 7),	\
 		show_dts_mode, NULL, NOT_USED, index - 7),	\
@@ -1574,6 +1660,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 	SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO,		\
 	SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO,		\
 		show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) }
 		show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) }
 
 
+/* Don't change the attribute order, _beep is accessed by index
+ * somewhere else in the code */
 #define SENSOR_ATTR_TEMP(index) {					\
 #define SENSOR_ATTR_TEMP(index) {					\
 	SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
 	SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
 		show_temp_mode, store_temp_mode, NOT_USED, index - 1),	\
 		show_temp_mode, store_temp_mode, NOT_USED, index - 1),	\
@@ -1593,8 +1681,6 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 	SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO,		\
 	SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO,		\
 		show_alarm_beep, store_beep, BEEP_ENABLE,		\
 		show_alarm_beep, store_beep, BEEP_ENABLE,		\
 		index + (index > 4 ? 11 : 17)),				\
 		index + (index > 4 ? 11 : 17)),				\
-	SENSOR_ATTR_2(temp##index##_source_sel, S_IWUSR | S_IRUGO,	\
-		show_temp_src, store_temp_src, NOT_USED, index - 1),	\
 	SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO,	\
 	SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO,	\
 		show_temp_pwm_enable, store_temp_pwm_enable,		\
 		show_temp_pwm_enable, store_temp_pwm_enable,		\
 		TEMP_PWM_ENABLE, index - 1),				\
 		TEMP_PWM_ENABLE, index - 1),				\
@@ -1680,7 +1766,7 @@ static const struct sensor_device_attribute_2 w83795_fan[][4] = {
 	SENSOR_ATTR_FAN(14),
 	SENSOR_ATTR_FAN(14),
 };
 };
 
 
-static const struct sensor_device_attribute_2 w83795_temp[][29] = {
+static const struct sensor_device_attribute_2 w83795_temp[][28] = {
 	SENSOR_ATTR_TEMP(1),
 	SENSOR_ATTR_TEMP(1),
 	SENSOR_ATTR_TEMP(2),
 	SENSOR_ATTR_TEMP(2),
 	SENSOR_ATTR_TEMP(3),
 	SENSOR_ATTR_TEMP(3),
@@ -1700,7 +1786,7 @@ static const struct sensor_device_attribute_2 w83795_dts[][8] = {
 	SENSOR_ATTR_DTS(14),
 	SENSOR_ATTR_DTS(14),
 };
 };
 
 
-static const struct sensor_device_attribute_2 w83795_pwm[][7] = {
+static const struct sensor_device_attribute_2 w83795_pwm[][8] = {
 	SENSOR_ATTR_PWM(1),
 	SENSOR_ATTR_PWM(1),
 	SENSOR_ATTR_PWM(2),
 	SENSOR_ATTR_PWM(2),
 	SENSOR_ATTR_PWM(3),
 	SENSOR_ATTR_PWM(3),
@@ -1711,13 +1797,24 @@ static const struct sensor_device_attribute_2 w83795_pwm[][7] = {
 	SENSOR_ATTR_PWM(8),
 	SENSOR_ATTR_PWM(8),
 };
 };
 
 
+static const struct sensor_device_attribute_2 w83795_tss[6] = {
+	SENSOR_ATTR_2(temp1_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 0),
+	SENSOR_ATTR_2(temp2_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 1),
+	SENSOR_ATTR_2(temp3_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 2),
+	SENSOR_ATTR_2(temp4_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 3),
+	SENSOR_ATTR_2(temp5_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 4),
+	SENSOR_ATTR_2(temp6_source_sel, S_IWUSR | S_IRUGO,
+		      show_temp_src, store_temp_src, NOT_USED, 5),
+};
+
 static const struct sensor_device_attribute_2 sda_single_files[] = {
 static const struct sensor_device_attribute_2 sda_single_files[] = {
 	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
 	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
 		      store_chassis_clear, ALARM_STATUS, 46),
 		      store_chassis_clear, ALARM_STATUS, 46),
-	SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep,
-		      store_beep, BEEP_ENABLE, 46),
-	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep,
-		      store_beep, BEEP_ENABLE, 47),
 #ifdef CONFIG_SENSORS_W83795_FANCTRL
 #ifdef CONFIG_SENSORS_W83795_FANCTRL
 	SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin,
 	SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin,
 		store_fanin, FANIN_TOL, NOT_USED),
 		store_fanin, FANIN_TOL, NOT_USED),
@@ -1730,6 +1827,13 @@ static const struct sensor_device_attribute_2 sda_single_files[] = {
 #endif
 #endif
 };
 };
 
 
+static const struct sensor_device_attribute_2 sda_beep_files[] = {
+	SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep,
+		      store_beep, BEEP_ENABLE, 46),
+	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep,
+		      store_beep, BEEP_ENABLE, 47),
+};
+
 /*
 /*
  * Driver interface
  * Driver interface
  */
  */
@@ -1859,6 +1963,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
 		if (!(data->has_in & (1 << i)))
 		if (!(data->has_in & (1 << i)))
 			continue;
 			continue;
 		for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) {
 		for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) {
+			if (j == 4 && !data->enable_beep)
+				continue;
 			err = fn(dev, &w83795_in[i][j].dev_attr);
 			err = fn(dev, &w83795_in[i][j].dev_attr);
 			if (err)
 			if (err)
 				return err;
 				return err;
@@ -1869,18 +1975,37 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
 		if (!(data->has_fan & (1 << i)))
 		if (!(data->has_fan & (1 << i)))
 			continue;
 			continue;
 		for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) {
 		for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) {
+			if (j == 3 && !data->enable_beep)
+				continue;
 			err = fn(dev, &w83795_fan[i][j].dev_attr);
 			err = fn(dev, &w83795_fan[i][j].dev_attr);
 			if (err)
 			if (err)
 				return err;
 				return err;
 		}
 		}
 	}
 	}
 
 
+	for (i = 0; i < ARRAY_SIZE(w83795_tss); i++) {
+		j = w83795_tss_useful(data, i);
+		if (!j)
+			continue;
+		err = fn(dev, &w83795_tss[i].dev_attr);
+		if (err)
+			return err;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
 	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
 		err = fn(dev, &sda_single_files[i].dev_attr);
 		err = fn(dev, &sda_single_files[i].dev_attr);
 		if (err)
 		if (err)
 			return err;
 			return err;
 	}
 	}
 
 
+	if (data->enable_beep) {
+		for (i = 0; i < ARRAY_SIZE(sda_beep_files); i++) {
+			err = fn(dev, &sda_beep_files[i].dev_attr);
+			if (err)
+				return err;
+		}
+	}
+
 #ifdef CONFIG_SENSORS_W83795_FANCTRL
 #ifdef CONFIG_SENSORS_W83795_FANCTRL
 	for (i = 0; i < data->has_pwm; i++) {
 	for (i = 0; i < data->has_pwm; i++) {
 		for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) {
 		for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) {
@@ -1899,6 +2024,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
 #else
 #else
 		for (j = 0; j < 8; j++) {
 		for (j = 0; j < 8; j++) {
 #endif
 #endif
+			if (j == 7 && !data->enable_beep)
+				continue;
 			err = fn(dev, &w83795_temp[i][j].dev_attr);
 			err = fn(dev, &w83795_temp[i][j].dev_attr);
 			if (err)
 			if (err)
 				return err;
 				return err;
@@ -1910,6 +2037,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
 			if (!(data->has_dts & (1 << i)))
 			if (!(data->has_dts & (1 << i)))
 				continue;
 				continue;
 			for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) {
 			for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) {
+				if (j == 7 && !data->enable_beep)
+					continue;
 				err = fn(dev, &w83795_dts[i][j].dev_attr);
 				err = fn(dev, &w83795_dts[i][j].dev_attr);
 				if (err)
 				if (err)
 					return err;
 					return err;
@@ -2049,6 +2178,18 @@ static int w83795_probe(struct i2c_client *client,
 	else
 	else
 		data->has_pwm = 2;
 		data->has_pwm = 2;
 
 
+	/* Check if BEEP pin is available */
+	if (data->chip_type == w83795g) {
+		/* The W83795G has a dedicated BEEP pin */
+		data->enable_beep = 1;
+	} else {
+		/* The W83795ADG has a shared pin for OVT# and BEEP, so you
+		 * can't have both */
+		tmp = w83795_read(client, W83795_REG_OVT_CFG);
+		if ((tmp & OVT_CFG_SEL) == 0)
+			data->enable_beep = 1;
+	}
+
 	err = w83795_handle_files(dev, device_create_file);
 	err = w83795_handle_files(dev, device_create_file);
 	if (err)
 	if (err)
 		goto exit_remove;
 		goto exit_remove;

+ 12 - 0
drivers/i2c/i2c-core.c

@@ -848,6 +848,18 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 		goto out_list;
 		goto out_list;
 	}
 	}
 
 
+	/* Sanity checks */
+	if (unlikely(adap->name[0] == '\0')) {
+		pr_err("i2c-core: Attempt to register an adapter with "
+		       "no name!\n");
+		return -EINVAL;
+	}
+	if (unlikely(!adap->algo)) {
+		pr_err("i2c-core: Attempt to register adapter '%s' with "
+		       "no algo!\n", adap->name);
+		return -EINVAL;
+	}
+
 	rt_mutex_init(&adap->bus_lock);
 	rt_mutex_init(&adap->bus_lock);
 	mutex_init(&adap->userspace_clients_lock);
 	mutex_init(&adap->userspace_clients_lock);
 	INIT_LIST_HEAD(&adap->userspace_clients);
 	INIT_LIST_HEAD(&adap->userspace_clients);

+ 0 - 1
drivers/i2c/i2c-mux.c

@@ -120,7 +120,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 	snprintf(priv->adap.name, sizeof(priv->adap.name),
 	snprintf(priv->adap.name, sizeof(priv->adap.name),
 		 "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id);
 		 "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id);
 	priv->adap.owner = THIS_MODULE;
 	priv->adap.owner = THIS_MODULE;
-	priv->adap.id = parent->id;
 	priv->adap.algo = &priv->algo;
 	priv->adap.algo = &priv->algo;
 	priv->adap.algo_data = priv;
 	priv->adap.algo_data = priv;
 	priv->adap.dev.parent = &parent->dev;
 	priv->adap.dev.parent = &parent->dev;

+ 11 - 9
drivers/md/dm-table.c

@@ -325,15 +325,18 @@ static int open_dev(struct dm_dev_internal *d, dev_t dev,
 
 
 	BUG_ON(d->dm_dev.bdev);
 	BUG_ON(d->dm_dev.bdev);
 
 
-	bdev = open_by_devnum(dev, d->dm_dev.mode);
+	bdev = blkdev_get_by_dev(dev, d->dm_dev.mode | FMODE_EXCL, _claim_ptr);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
 		return PTR_ERR(bdev);
-	r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md));
-	if (r)
-		blkdev_put(bdev, d->dm_dev.mode);
-	else
-		d->dm_dev.bdev = bdev;
-	return r;
+
+	r = bd_link_disk_holder(bdev, dm_disk(md));
+	if (r) {
+		blkdev_put(bdev, d->dm_dev.mode | FMODE_EXCL);
+		return r;
+	}
+
+	d->dm_dev.bdev = bdev;
+	return 0;
 }
 }
 
 
 /*
 /*
@@ -344,8 +347,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
 	if (!d->dm_dev.bdev)
 	if (!d->dm_dev.bdev)
 		return;
 		return;
 
 
-	bd_release_from_disk(d->dm_dev.bdev, dm_disk(md));
-	blkdev_put(d->dm_dev.bdev, d->dm_dev.mode);
+	blkdev_put(d->dm_dev.bdev, d->dm_dev.mode | FMODE_EXCL);
 	d->dm_dev.bdev = NULL;
 	d->dm_dev.bdev = NULL;
 }
 }
 
 

+ 2 - 2
drivers/md/dm.c

@@ -990,8 +990,8 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
 	if (r == DM_MAPIO_REMAPPED) {
 	if (r == DM_MAPIO_REMAPPED) {
 		/* the bio has been remapped so dispatch it */
 		/* the bio has been remapped so dispatch it */
 
 
-		trace_block_remap(bdev_get_queue(clone->bi_bdev), clone,
-				    tio->io->bio->bi_bdev->bd_dev, sector);
+		trace_block_bio_remap(bdev_get_queue(clone->bi_bdev), clone,
+				      tio->io->bio->bi_bdev->bd_dev, sector);
 
 
 		generic_make_request(clone);
 		generic_make_request(clone);
 	} else if (r < 0 || r == DM_MAPIO_REQUEUE) {
 	} else if (r < 0 || r == DM_MAPIO_REQUEUE) {

+ 4 - 12
drivers/md/md.c

@@ -1880,7 +1880,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 	rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state");
 	rdev->sysfs_state = sysfs_get_dirent_safe(rdev->kobj.sd, "state");
 
 
 	list_add_rcu(&rdev->same_set, &mddev->disks);
 	list_add_rcu(&rdev->same_set, &mddev->disks);
-	bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
+	bd_link_disk_holder(rdev->bdev, mddev->gendisk);
 
 
 	/* May as well allow recovery to be retried once */
 	/* May as well allow recovery to be retried once */
 	mddev->recovery_disabled = 0;
 	mddev->recovery_disabled = 0;
@@ -1907,7 +1907,6 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
 		MD_BUG();
 		MD_BUG();
 		return;
 		return;
 	}
 	}
-	bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
 	list_del_rcu(&rdev->same_set);
 	list_del_rcu(&rdev->same_set);
 	printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
 	printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
 	rdev->mddev = NULL;
 	rdev->mddev = NULL;
@@ -1935,19 +1934,13 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
 	struct block_device *bdev;
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 	char b[BDEVNAME_SIZE];
 
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				 shared ? (mdk_rdev_t *)lock_rdev : rdev);
 	if (IS_ERR(bdev)) {
 	if (IS_ERR(bdev)) {
 		printk(KERN_ERR "md: could not open %s.\n",
 		printk(KERN_ERR "md: could not open %s.\n",
 			__bdevname(dev, b));
 			__bdevname(dev, b));
 		return PTR_ERR(bdev);
 		return PTR_ERR(bdev);
 	}
 	}
-	err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);
-	if (err) {
-		printk(KERN_ERR "md: could not bd_claim %s.\n",
-			bdevname(bdev, b));
-		blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
-		return err;
-	}
 	if (!shared)
 	if (!shared)
 		set_bit(AllReserved, &rdev->flags);
 		set_bit(AllReserved, &rdev->flags);
 	rdev->bdev = bdev;
 	rdev->bdev = bdev;
@@ -1960,8 +1953,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
 	rdev->bdev = NULL;
 	rdev->bdev = NULL;
 	if (!bdev)
 	if (!bdev)
 		MD_BUG();
 		MD_BUG();
-	bd_release(bdev);
-	blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 }
 
 
 void md_autodetect_dev(dev_t dev);
 void md_autodetect_dev(dev_t dev);

+ 0 - 1
drivers/media/common/saa7146_i2c.c

@@ -391,7 +391,6 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in
 
 
 /*****************************************************************************/
 /*****************************************************************************/
 /* i2c-adapter helper functions                                              */
 /* i2c-adapter helper functions                                              */
-#include <linux/i2c-id.h>
 
 
 /* exported algorithm data */
 /* exported algorithm data */
 static struct i2c_algorithm saa7146_algo = {
 static struct i2c_algorithm saa7146_algo = {

+ 0 - 2
drivers/media/video/imx074.c

@@ -451,7 +451,6 @@ static int imx074_probe(struct i2c_client *client,
 	ret = imx074_video_probe(icd, client);
 	ret = imx074_video_probe(icd, client);
 	if (ret < 0) {
 	if (ret < 0) {
 		icd->ops = NULL;
 		icd->ops = NULL;
-		i2c_set_clientdata(client, NULL);
 		kfree(priv);
 		kfree(priv);
 		return ret;
 		return ret;
 	}
 	}
@@ -468,7 +467,6 @@ static int imx074_remove(struct i2c_client *client)
 	icd->ops = NULL;
 	icd->ops = NULL;
 	if (icl->free_bus)
 	if (icl->free_bus)
 		icl->free_bus(icl);
 		icl->free_bus(icl);
-	i2c_set_clientdata(client, NULL);
 	client->driver = NULL;
 	client->driver = NULL;
 	kfree(priv);
 	kfree(priv);
 
 

+ 0 - 1
drivers/media/video/ir-kbd-i2c.c

@@ -44,7 +44,6 @@
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
-#include <linux/i2c-id.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 
 
 #include <media/ir-core.h>
 #include <media/ir-core.h>

+ 0 - 2
drivers/media/video/ov6650.c

@@ -1174,7 +1174,6 @@ static int ov6650_probe(struct i2c_client *client,
 
 
 	if (ret) {
 	if (ret) {
 		icd->ops = NULL;
 		icd->ops = NULL;
-		i2c_set_clientdata(client, NULL);
 		kfree(priv);
 		kfree(priv);
 	}
 	}
 
 
@@ -1185,7 +1184,6 @@ static int ov6650_remove(struct i2c_client *client)
 {
 {
 	struct ov6650 *priv = to_ov6650(client);
 	struct ov6650 *priv = to_ov6650(client);
 
 
-	i2c_set_clientdata(client, NULL);
 	kfree(priv);
 	kfree(priv);
 	return 0;
 	return 0;
 }
 }

+ 0 - 1
drivers/misc/apds9802als.c

@@ -251,7 +251,6 @@ static int apds9802als_probe(struct i2c_client *client,
 
 
 	return res;
 	return res;
 als_error1:
 als_error1:
-	i2c_set_clientdata(client, NULL);
 	kfree(data);
 	kfree(data);
 	return res;
 	return res;
 }
 }

+ 5 - 5
drivers/mtd/devices/block2mtd.c

@@ -224,7 +224,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 	if (dev->blkdev) {
 	if (dev->blkdev) {
 		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
 		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
 					0, -1);
 					0, -1);
-		close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
+		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 	}
 	}
 
 
 	kfree(dev);
 	kfree(dev);
@@ -234,6 +234,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 /* FIXME: ensure that mtd->size % erase_size == 0 */
 /* FIXME: ensure that mtd->size % erase_size == 0 */
 static struct block2mtd_dev *add_device(char *devname, int erase_size)
 static struct block2mtd_dev *add_device(char *devname, int erase_size)
 {
 {
+	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 	struct block_device *bdev;
 	struct block_device *bdev;
 	struct block2mtd_dev *dev;
 	struct block2mtd_dev *dev;
 	char *name;
 	char *name;
@@ -246,7 +247,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 		return NULL;
 		return NULL;
 
 
 	/* Get a handle on the device */
 	/* Get a handle on the device */
-	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
+	bdev = blkdev_get_by_path(devname, mode, dev);
 #ifndef MODULE
 #ifndef MODULE
 	if (IS_ERR(bdev)) {
 	if (IS_ERR(bdev)) {
 
 
@@ -254,9 +255,8 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 		   to resolve the device name by other means. */
 		   to resolve the device name by other means. */
 
 
 		dev_t devt = name_to_dev_t(devname);
 		dev_t devt = name_to_dev_t(devname);
-		if (devt) {
-			bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
-		}
+		if (devt)
+			bdev = blkdev_get_by_dev(devt, mode, dev);
 	}
 	}
 #endif
 #endif
 
 

+ 49 - 21
drivers/pci/bus.c

@@ -64,17 +64,57 @@ void pci_bus_remove_resources(struct pci_bus *bus)
 	}
 	}
 }
 }
 
 
+static bool pci_bus_resource_better(struct resource *res1, bool pos1,
+				    struct resource *res2, bool pos2)
+{
+	/* If exactly one is positive decode, always prefer that one */
+	if (pos1 != pos2)
+		return pos1 ? true : false;
+
+	/* Prefer the one that contains the highest address */
+	if (res1->end != res2->end)
+		return (res1->end > res2->end) ? true : false;
+
+	/* Otherwise, prefer the one with highest "center of gravity" */
+	if (res1->start != res2->start)
+		return (res1->start > res2->start) ? true : false;
+
+	/* Otherwise, choose one arbitrarily (but consistently) */
+	return (res1 > res2) ? true : false;
+}
+
+static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
+{
+	struct pci_bus_resource *bus_res;
+
+	/*
+	 * This relies on the fact that pci_bus.resource[] refers to P2P or
+	 * CardBus bridge base/limit registers, which are always positively
+	 * decoded.  The pci_bus.resources list contains host bridge or
+	 * subtractively decoded resources.
+	 */
+	list_for_each_entry(bus_res, &bus->resources, list) {
+		if (bus_res->res == res)
+			return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
+				false : true;
+	}
+	return true;
+}
+
 /*
 /*
- * Find the highest-address bus resource below the cursor "res".  If the
- * cursor is NULL, return the highest resource.
+ * Find the next-best bus resource after the cursor "res".  If the cursor is
+ * NULL, return the best resource.  "Best" means that we prefer positive
+ * decode regions over subtractive decode, then those at higher addresses.
  */
  */
 static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
 static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
 						   unsigned int type,
 						   unsigned int type,
 						   struct resource *res)
 						   struct resource *res)
 {
 {
+	bool res_pos, r_pos, prev_pos = false;
 	struct resource *r, *prev = NULL;
 	struct resource *r, *prev = NULL;
 	int i;
 	int i;
 
 
+	res_pos = pci_bus_resource_positive(bus, res);
 	pci_bus_for_each_resource(bus, r, i) {
 	pci_bus_for_each_resource(bus, r, i) {
 		if (!r)
 		if (!r)
 			continue;
 			continue;
@@ -82,26 +122,14 @@ static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
 		if ((r->flags & IORESOURCE_TYPE_BITS) != type)
 		if ((r->flags & IORESOURCE_TYPE_BITS) != type)
 			continue;
 			continue;
 
 
-		/* If this resource is at or past the cursor, skip it */
-		if (res) {
-			if (r == res)
-				continue;
-			if (r->end > res->end)
-				continue;
-			if (r->end == res->end && r->start > res->start)
-				continue;
+		r_pos = pci_bus_resource_positive(bus, r);
+		if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) {
+			if (!prev || pci_bus_resource_better(r, r_pos,
+							     prev, prev_pos)) {
+				prev = r;
+				prev_pos = r_pos;
+			}
 		}
 		}
-
-		if (!prev)
-			prev = r;
-
-		/*
-		 * A small resource is higher than a large one that ends at
-		 * the same address.
-		 */
-		if (r->end > prev->end ||
-		    (r->end == prev->end && r->start > prev->start))
-			prev = r;
 	}
 	}
 
 
 	return prev;
 	return prev;

+ 6 - 0
drivers/pci/hotplug/ibmphp_ebda.c

@@ -276,6 +276,12 @@ int __init ibmphp_access_ebda (void)
 
 
 	for (;;) {
 	for (;;) {
 		offset = next_offset;
 		offset = next_offset;
+
+		/* Make sure what we read is still in the mapped section */
+		if (WARN(offset > (ebda_sz * 1024 - 4),
+			 "ibmphp_ebda: next read is beyond ebda_sz\n"))
+			break;
+
 		next_offset = readw (io_mem + offset);	/* offset of next blk */
 		next_offset = readw (io_mem + offset);	/* offset of next blk */
 
 
 		offset += 2;
 		offset += 2;

+ 17 - 6
drivers/pci/pci-sysfs.c

@@ -705,17 +705,21 @@ void pci_remove_legacy_files(struct pci_bus *b)
 
 
 #ifdef HAVE_PCI_MMAP
 #ifdef HAVE_PCI_MMAP
 
 
-int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
+		  enum pci_mmap_api mmap_api)
 {
 {
-	unsigned long nr, start, size;
+	unsigned long nr, start, size, pci_start;
 
 
+	if (pci_resource_len(pdev, resno) == 0)
+		return 0;
 	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	start = vma->vm_pgoff;
 	start = vma->vm_pgoff;
 	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
 	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-	if (start < size && size - start >= nr)
+	pci_start = (mmap_api == PCI_MMAP_SYSFS) ?
+			pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+	if (start >= pci_start && start < pci_start + size &&
+			start + nr <= pci_start + size)
 		return 1;
 		return 1;
-	WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
-		current->comm, start, start+nr, pci_name(pdev), resno, size);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -745,8 +749,15 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
 	if (i >= PCI_ROM_RESOURCE)
 	if (i >= PCI_ROM_RESOURCE)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (!pci_mmap_fits(pdev, i, vma))
+	if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
+		WARN(1, "process \"%s\" tried to map 0x%08lx bytes "
+			"at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
+			current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
+			pci_name(pdev), i,
+			(u64)pci_resource_start(pdev, i),
+			(u64)pci_resource_len(pdev, i));
 		return -EINVAL;
 		return -EINVAL;
+	}
 
 
 	/* pci_mmap_page_range() expects the same kind of entry as coming
 	/* pci_mmap_page_range() expects the same kind of entry as coming
 	 * from /proc/bus/pci/ which is a "user visible" value. If this is
 	 * from /proc/bus/pci/ which is a "user visible" value. If this is

+ 12 - 0
drivers/pci/pci.c

@@ -1007,6 +1007,18 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
 	int err;
 	int err;
 	int i, bars = 0;
 	int i, bars = 0;
 
 
+	/*
+	 * Power state could be unknown at this point, either due to a fresh
+	 * boot or a device removal call.  So get the current power state
+	 * so that things like MSI message writing will behave as expected
+	 * (e.g. if the device really is in D0 at enable time).
+	 */
+	if (dev->pm_cap) {
+		u16 pmcsr;
+		pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
+		dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+	}
+
 	if (atomic_add_return(1, &dev->enable_cnt) > 1)
 	if (atomic_add_return(1, &dev->enable_cnt) > 1)
 		return 0;		/* already enabled */
 		return 0;		/* already enabled */
 
 

+ 6 - 1
drivers/pci/pci.h

@@ -22,8 +22,13 @@ extern void pci_remove_firmware_label_files(struct pci_dev *pdev);
 #endif
 #endif
 extern void pci_cleanup_rom(struct pci_dev *dev);
 extern void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef HAVE_PCI_MMAP
 #ifdef HAVE_PCI_MMAP
+enum pci_mmap_api {
+	PCI_MMAP_SYSFS,	/* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
+	PCI_MMAP_PROCFS	/* mmap on /proc/bus/pci/<BDF> */
+};
 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
 extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
-			 struct vm_area_struct *vma);
+			 struct vm_area_struct *vmai,
+			 enum pci_mmap_api mmap_api);
 #endif
 #endif
 int pci_probe_reset_function(struct pci_dev *dev);
 int pci_probe_reset_function(struct pci_dev *dev);
 
 

+ 1 - 1
drivers/pci/proc.c

@@ -257,7 +257,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 
 
 	/* Make sure the caller is mapping a real resource for this device */
 	/* Make sure the caller is mapping a real resource for this device */
 	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
 	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-		if (pci_mmap_fits(dev, i, vma))
+		if (pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
 			break;
 			break;
 	}
 	}
 
 

+ 2 - 2
drivers/rtc/rtc-sh.c

@@ -761,7 +761,7 @@ err_unmap:
 	clk_put(rtc->clk);
 	clk_put(rtc->clk);
 	iounmap(rtc->regbase);
 	iounmap(rtc->regbase);
 err_badmap:
 err_badmap:
-	release_resource(rtc->res);
+	release_mem_region(rtc->res->start, rtc->regsize);
 err_badres:
 err_badres:
 	kfree(rtc);
 	kfree(rtc);
 
 
@@ -786,7 +786,7 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
 	}
 	}
 
 
 	iounmap(rtc->regbase);
 	iounmap(rtc->regbase);
-	release_resource(rtc->res);
+	release_mem_region(rtc->res->start, rtc->regsize);
 
 
 	clk_disable(rtc->clk);
 	clk_disable(rtc->clk);
 	clk_put(rtc->clk);
 	clk_put(rtc->clk);

+ 1 - 1
drivers/s390/block/dasd_genhd.c

@@ -103,7 +103,7 @@ int dasd_scan_partitions(struct dasd_block *block)
 	struct block_device *bdev;
 	struct block_device *bdev;
 
 
 	bdev = bdget_disk(block->gdp, 0);
 	bdev = bdget_disk(block->gdp, 0);
-	if (!bdev || blkdev_get(bdev, FMODE_READ) < 0)
+	if (!bdev || blkdev_get(bdev, FMODE_READ, NULL) < 0)
 		return -ENODEV;
 		return -ENODEV;
 	/*
 	/*
 	 * See fs/partition/check.c:register_disk,rescan_partitions
 	 * See fs/partition/check.c:register_disk,rescan_partitions

+ 2 - 2
drivers/sh/clk/core.c

@@ -571,7 +571,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
 					*best_freq = freq_max;
 					*best_freq = freq_max;
 			}
 			}
 
 
-			pr_debug("too low freq %lu, error %lu\n", freq->frequency,
+			pr_debug("too low freq %u, error %lu\n", freq->frequency,
 				 target - freq_max);
 				 target - freq_max);
 
 
 			if (!error)
 			if (!error)
@@ -591,7 +591,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,
 					*best_freq = freq_min;
 					*best_freq = freq_min;
 			}
 			}
 
 
-			pr_debug("too high freq %lu, error %lu\n", freq->frequency,
+			pr_debug("too high freq %u, error %lu\n", freq->frequency,
 				 freq_min - target);
 				 freq_min - target);
 
 
 			if (!error)
 			if (!error)

+ 1 - 1
drivers/sh/intc/virq.c

@@ -215,7 +215,7 @@ restart:
 		entry = radix_tree_deref_slot((void **)entries[i]);
 		entry = radix_tree_deref_slot((void **)entries[i]);
 		if (unlikely(!entry))
 		if (unlikely(!entry))
 			continue;
 			continue;
-		if (unlikely(entry == RADIX_TREE_RETRY))
+		if (radix_tree_deref_retry(entry))
 			goto restart;
 			goto restart;
 
 
 		irq = create_irq();
 		irq = create_irq();

+ 0 - 4
drivers/staging/olpc_dcon/olpc_dcon.c

@@ -17,7 +17,6 @@
 #include <linux/console.h>
 #include <linux/console.h>
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
-#include <linux/i2c-id.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/pci_ids.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
@@ -733,7 +732,6 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
  edev:
  edev:
 	platform_device_unregister(dcon_device);
 	platform_device_unregister(dcon_device);
 	dcon_device = NULL;
 	dcon_device = NULL;
-	i2c_set_clientdata(client, NULL);
  eirq:
  eirq:
 	free_irq(DCON_IRQ, &dcon_driver);
 	free_irq(DCON_IRQ, &dcon_driver);
  einit:
  einit:
@@ -757,8 +755,6 @@ static int dcon_remove(struct i2c_client *client)
 		platform_device_unregister(dcon_device);
 		platform_device_unregister(dcon_device);
 	cancel_work_sync(&dcon_work);
 	cancel_work_sync(&dcon_work);
 
 
-	i2c_set_clientdata(client, NULL);
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 2 - 5
drivers/usb/gadget/storage_common.c

@@ -543,7 +543,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 	ro = curlun->initially_ro;
 	ro = curlun->initially_ro;
 	if (!ro) {
 	if (!ro) {
 		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
 		filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
-		if (-EROFS == PTR_ERR(filp))
+		if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)
 			ro = 1;
 			ro = 1;
 	}
 	}
 	if (ro)
 	if (ro)
@@ -558,10 +558,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 
 
 	if (filp->f_path.dentry)
 	if (filp->f_path.dentry)
 		inode = filp->f_path.dentry->d_inode;
 		inode = filp->f_path.dentry->d_inode;
-	if (inode && S_ISBLK(inode->i_mode)) {
-		if (bdev_read_only(inode->i_bdev))
-			ro = 1;
-	} else if (!inode || !S_ISREG(inode->i_mode)) {
+	if (!inode || (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
 		LINFO(curlun, "invalid file type: %s\n", filename);
 		LINFO(curlun, "invalid file type: %s\n", filename);
 		goto out;
 		goto out;
 	}
 	}

+ 13 - 4
drivers/video/omap2/vram.c

@@ -554,9 +554,15 @@ void __init omap_vram_reserve_sdram_memblock(void)
 	size = PAGE_ALIGN(size);
 	size = PAGE_ALIGN(size);
 
 
 	if (paddr) {
 	if (paddr) {
-		if ((paddr & ~PAGE_MASK) ||
-		    !memblock_is_region_memory(paddr, size)) {
-			pr_err("Illegal SDRAM region for VRAM\n");
+		if (paddr & ~PAGE_MASK) {
+			pr_err("VRAM start address 0x%08x not page aligned\n",
+					paddr);
+			return;
+		}
+
+		if (!memblock_is_region_memory(paddr, size)) {
+			pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n",
+					paddr, paddr + size - 1);
 			return;
 			return;
 		}
 		}
 
 
@@ -570,9 +576,12 @@ void __init omap_vram_reserve_sdram_memblock(void)
 			return;
 			return;
 		}
 		}
 	} else {
 	} else {
-		paddr = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_REAL_LIMIT);
+		paddr = memblock_alloc(size, PAGE_SIZE);
 	}
 	}
 
 
+	memblock_free(paddr, size);
+	memblock_remove(paddr, size);
+
 	omap_vram_add_region(paddr, size);
 	omap_vram_add_region(paddr, size);
 
 
 	pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
 	pr_info("Reserving %u bytes SDRAM for VRAM\n", size);

+ 0 - 1
drivers/video/riva/rivafb-i2c.c

@@ -94,7 +94,6 @@ static int __devinit riva_setup_i2c_bus(struct riva_i2c_chan *chan,
 
 
 	strcpy(chan->adapter.name, name);
 	strcpy(chan->adapter.name, name);
 	chan->adapter.owner		= THIS_MODULE;
 	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.id		= I2C_HW_B_RIVA;
 	chan->adapter.class		= i2c_class;
 	chan->adapter.class		= i2c_class;
 	chan->adapter.algo_data		= &chan->algo;
 	chan->adapter.algo_data		= &chan->algo;
 	chan->adapter.dev.parent	= &chan->par->pdev->dev;
 	chan->adapter.dev.parent	= &chan->par->pdev->dev;

+ 4 - 1
drivers/video/sh_mobile_hdmi.c

@@ -1071,6 +1071,10 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 		if (!hdmi->info)
 		if (!hdmi->info)
 			goto out;
 			goto out;
 
 
+		hdmi->monspec.modedb_len = 0;
+		fb_destroy_modedb(hdmi->monspec.modedb);
+		hdmi->monspec.modedb = NULL;
+
 		acquire_console_sem();
 		acquire_console_sem();
 
 
 		/* HDMI disconnect */
 		/* HDMI disconnect */
@@ -1078,7 +1082,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 
 
 		release_console_sem();
 		release_console_sem();
 		pm_runtime_put(hdmi->dev);
 		pm_runtime_put(hdmi->dev);
-		fb_destroy_modedb(hdmi->monspec.modedb);
 	}
 	}
 
 
 out:
 out:

+ 12 - 9
drivers/video/sh_mobile_lcdcfb.c

@@ -115,15 +115,16 @@ static const struct fb_videomode default_720p = {
 	.xres = 1280,
 	.xres = 1280,
 	.yres = 720,
 	.yres = 720,
 
 
-	.left_margin = 200,
-	.right_margin = 88,
-	.hsync_len = 48,
+	.left_margin = 220,
+	.right_margin = 110,
+	.hsync_len = 40,
 
 
 	.upper_margin = 20,
 	.upper_margin = 20,
 	.lower_margin = 5,
 	.lower_margin = 5,
 	.vsync_len = 5,
 	.vsync_len = 5,
 
 
 	.pixclock = 13468,
 	.pixclock = 13468,
+	.refresh = 60,
 	.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
 	.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
 };
 };
 
 
@@ -1197,6 +1198,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		const struct fb_videomode *mode = cfg->lcd_cfg;
 		const struct fb_videomode *mode = cfg->lcd_cfg;
 		unsigned long max_size = 0;
 		unsigned long max_size = 0;
 		int k;
 		int k;
+		int num_cfg;
 
 
 		ch->info = framebuffer_alloc(0, &pdev->dev);
 		ch->info = framebuffer_alloc(0, &pdev->dev);
 		if (!ch->info) {
 		if (!ch->info) {
@@ -1232,8 +1234,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		info->fix = sh_mobile_lcdc_fix;
 		info->fix = sh_mobile_lcdc_fix;
 		info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
 		info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
 
 
-		if (!mode)
+		if (!mode) {
 			mode = &default_720p;
 			mode = &default_720p;
+			num_cfg = 1;
+		} else {
+			num_cfg = ch->cfg.num_cfg;
+		}
+
+		fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
 
 
 		fb_videomode_to_var(var, mode);
 		fb_videomode_to_var(var, mode);
 		/* Default Y virtual resolution is 2x panel size */
 		/* Default Y virtual resolution is 2x panel size */
@@ -1281,10 +1289,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 
 
 	for (i = 0; i < j; i++) {
 	for (i = 0; i < j; i++) {
 		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
 		struct sh_mobile_lcdc_chan *ch = priv->ch + i;
-		const struct fb_videomode *mode = ch->cfg.lcd_cfg;
-
-		if (!mode)
-			mode = &default_720p;
 
 
 		info = ch->info;
 		info = ch->info;
 
 
@@ -1297,7 +1301,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 			}
 			}
 		}
 		}
 
 
-		fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist);
 		error = register_framebuffer(info);
 		error = register_framebuffer(info);
 		if (error < 0)
 		if (error < 0)
 			goto err1;
 			goto err1;

+ 6 - 2
drivers/video/sis/sis_main.c

@@ -4181,6 +4181,9 @@ static void __devinit
 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
 sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
 			unsigned int min)
 			unsigned int min)
 {
 {
+	if (*mapsize < (min << 20))
+		return;
+
 	ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
 	ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
 
 
 	if(!ivideo->video_vbase) {
 	if(!ivideo->video_vbase) {
@@ -4514,7 +4517,7 @@ sisfb_post_sis300(struct pci_dev *pdev)
 	} else {
 	} else {
 #endif
 #endif
 		/* Need to map max FB size for finding out about RAM size */
 		/* Need to map max FB size for finding out about RAM size */
-		mapsize = 64 << 20;
+		mapsize = ivideo->video_size;
 		sisfb_post_map_vram(ivideo, &mapsize, 4);
 		sisfb_post_map_vram(ivideo, &mapsize, 4);
 
 
 		if(ivideo->video_vbase) {
 		if(ivideo->video_vbase) {
@@ -4680,7 +4683,7 @@ sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
 	orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
 	orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
 
 
 	/* Need to map max FB size for finding out about RAM size */
 	/* Need to map max FB size for finding out about RAM size */
-	mapsize = 256 << 20;
+	mapsize = ivideo->video_size;
 	sisfb_post_map_vram(ivideo, &mapsize, 32);
 	sisfb_post_map_vram(ivideo, &mapsize, 32);
 
 
 	if(!ivideo->video_vbase) {
 	if(!ivideo->video_vbase) {
@@ -5936,6 +5939,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	}
 
 
 	ivideo->video_base = pci_resource_start(pdev, 0);
 	ivideo->video_base = pci_resource_start(pdev, 0);
+	ivideo->video_size = pci_resource_len(pdev, 0);
 	ivideo->mmio_base  = pci_resource_start(pdev, 1);
 	ivideo->mmio_base  = pci_resource_start(pdev, 1);
 	ivideo->mmio_size  = pci_resource_len(pdev, 1);
 	ivideo->mmio_size  = pci_resource_len(pdev, 1);
 	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
 	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;

+ 221 - 487
fs/block_dev.c

@@ -426,9 +426,6 @@ static void init_once(void *foo)
 	mutex_init(&bdev->bd_mutex);
 	mutex_init(&bdev->bd_mutex);
 	INIT_LIST_HEAD(&bdev->bd_inodes);
 	INIT_LIST_HEAD(&bdev->bd_inodes);
 	INIT_LIST_HEAD(&bdev->bd_list);
 	INIT_LIST_HEAD(&bdev->bd_list);
-#ifdef CONFIG_SYSFS
-	INIT_LIST_HEAD(&bdev->bd_holder_list);
-#endif
 	inode_init_once(&ei->vfs_inode);
 	inode_init_once(&ei->vfs_inode);
 	/* Initialize mutex for freeze. */
 	/* Initialize mutex for freeze. */
 	mutex_init(&bdev->bd_fsfreeze_mutex);
 	mutex_init(&bdev->bd_fsfreeze_mutex);
@@ -663,7 +660,7 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole,
 	else if (bdev->bd_contains == bdev)
 	else if (bdev->bd_contains == bdev)
 		return true;  	 /* is a whole device which isn't held */
 		return true;  	 /* is a whole device which isn't held */
 
 
-	else if (whole->bd_holder == bd_claim)
+	else if (whole->bd_holder == bd_may_claim)
 		return true; 	 /* is a partition of a device that is being partitioned */
 		return true; 	 /* is a partition of a device that is being partitioned */
 	else if (whole->bd_holder != NULL)
 	else if (whole->bd_holder != NULL)
 		return false;	 /* is a partition of a held device */
 		return false;	 /* is a partition of a held device */
@@ -775,439 +772,87 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
 	}
 	}
 }
 }
 
 
-/* releases bdev_lock */
-static void __bd_abort_claiming(struct block_device *whole, void *holder)
-{
-	BUG_ON(whole->bd_claiming != holder);
-	whole->bd_claiming = NULL;
-	wake_up_bit(&whole->bd_claiming, 0);
-
-	spin_unlock(&bdev_lock);
-	bdput(whole);
-}
-
-/**
- * bd_abort_claiming - abort claiming a block device
- * @whole: whole block device returned by bd_start_claiming()
- * @holder: holder trying to claim @bdev
- *
- * Abort a claiming block started by bd_start_claiming().  Note that
- * @whole is not the block device to be claimed but the whole device
- * returned by bd_start_claiming().
- *
- * CONTEXT:
- * Grabs and releases bdev_lock.
- */
-static void bd_abort_claiming(struct block_device *whole, void *holder)
-{
-	spin_lock(&bdev_lock);
-	__bd_abort_claiming(whole, holder);		/* releases bdev_lock */
-}
-
-/* increment holders when we have a legitimate claim. requires bdev_lock */
-static void __bd_claim(struct block_device *bdev, struct block_device *whole,
-					void *holder)
-{
-	/* note that for a whole device bd_holders
-	 * will be incremented twice, and bd_holder will
-	 * be set to bd_claim before being set to holder
-	 */
-	whole->bd_holders++;
-	whole->bd_holder = bd_claim;
-	bdev->bd_holders++;
-	bdev->bd_holder = holder;
-}
-
-/**
- * bd_finish_claiming - finish claiming a block device
- * @bdev: block device of interest (passed to bd_start_claiming())
- * @whole: whole block device returned by bd_start_claiming()
- * @holder: holder trying to claim @bdev
- *
- * Finish a claiming block started by bd_start_claiming().
- *
- * CONTEXT:
- * Grabs and releases bdev_lock.
- */
-static void bd_finish_claiming(struct block_device *bdev,
-				struct block_device *whole, void *holder)
-{
-	spin_lock(&bdev_lock);
-	BUG_ON(!bd_may_claim(bdev, whole, holder));
-	__bd_claim(bdev, whole, holder);
-	__bd_abort_claiming(whole, holder); /* not actually an abort */
-}
-
-/**
- * bd_claim - claim a block device
- * @bdev: block device to claim
- * @holder: holder trying to claim @bdev
- *
- * Try to claim @bdev which must have been opened successfully.
- *
- * CONTEXT:
- * Might sleep.
- *
- * RETURNS:
- * 0 if successful, -EBUSY if @bdev is already claimed.
- */
-int bd_claim(struct block_device *bdev, void *holder)
-{
-	struct block_device *whole = bdev->bd_contains;
-	int res;
-
-	might_sleep();
-
-	spin_lock(&bdev_lock);
-	res = bd_prepare_to_claim(bdev, whole, holder);
-	if (res == 0)
-		__bd_claim(bdev, whole, holder);
-	spin_unlock(&bdev_lock);
-
-	return res;
-}
-EXPORT_SYMBOL(bd_claim);
-
-void bd_release(struct block_device *bdev)
-{
-	spin_lock(&bdev_lock);
-	if (!--bdev->bd_contains->bd_holders)
-		bdev->bd_contains->bd_holder = NULL;
-	if (!--bdev->bd_holders)
-		bdev->bd_holder = NULL;
-	spin_unlock(&bdev_lock);
-}
-
-EXPORT_SYMBOL(bd_release);
-
 #ifdef CONFIG_SYSFS
 #ifdef CONFIG_SYSFS
-/*
- * Functions for bd_claim_by_kobject / bd_release_from_kobject
- *
- *     If a kobject is passed to bd_claim_by_kobject()
- *     and the kobject has a parent directory,
- *     following symlinks are created:
- *        o from the kobject to the claimed bdev
- *        o from "holders" directory of the bdev to the parent of the kobject
- *     bd_release_from_kobject() removes these symlinks.
- *
- *     Example:
- *        If /dev/dm-0 maps to /dev/sda, kobject corresponding to
- *        /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:
- *           /sys/block/dm-0/slaves/sda --> /sys/block/sda
- *           /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
- */
-
 static int add_symlink(struct kobject *from, struct kobject *to)
 static int add_symlink(struct kobject *from, struct kobject *to)
 {
 {
-	if (!from || !to)
-		return 0;
 	return sysfs_create_link(from, to, kobject_name(to));
 	return sysfs_create_link(from, to, kobject_name(to));
 }
 }
 
 
 static void del_symlink(struct kobject *from, struct kobject *to)
 static void del_symlink(struct kobject *from, struct kobject *to)
 {
 {
-	if (!from || !to)
-		return;
 	sysfs_remove_link(from, kobject_name(to));
 	sysfs_remove_link(from, kobject_name(to));
 }
 }
 
 
-/*
- * 'struct bd_holder' contains pointers to kobjects symlinked by
- * bd_claim_by_kobject.
- * It's connected to bd_holder_list which is protected by bdev->bd_sem.
- */
-struct bd_holder {
-	struct list_head list;	/* chain of holders of the bdev */
-	int count;		/* references from the holder */
-	struct kobject *sdir;	/* holder object, e.g. "/block/dm-0/slaves" */
-	struct kobject *hdev;	/* e.g. "/block/dm-0" */
-	struct kobject *hdir;	/* e.g. "/block/sda/holders" */
-	struct kobject *sdev;	/* e.g. "/block/sda" */
-};
-
-/*
- * Get references of related kobjects at once.
- * Returns 1 on success. 0 on failure.
- *
- * Should call bd_holder_release_dirs() after successful use.
- */
-static int bd_holder_grab_dirs(struct block_device *bdev,
-			struct bd_holder *bo)
-{
-	if (!bdev || !bo)
-		return 0;
-
-	bo->sdir = kobject_get(bo->sdir);
-	if (!bo->sdir)
-		return 0;
-
-	bo->hdev = kobject_get(bo->sdir->parent);
-	if (!bo->hdev)
-		goto fail_put_sdir;
-
-	bo->sdev = kobject_get(&part_to_dev(bdev->bd_part)->kobj);
-	if (!bo->sdev)
-		goto fail_put_hdev;
-
-	bo->hdir = kobject_get(bdev->bd_part->holder_dir);
-	if (!bo->hdir)
-		goto fail_put_sdev;
-
-	return 1;
-
-fail_put_sdev:
-	kobject_put(bo->sdev);
-fail_put_hdev:
-	kobject_put(bo->hdev);
-fail_put_sdir:
-	kobject_put(bo->sdir);
-
-	return 0;
-}
-
-/* Put references of related kobjects at once. */
-static void bd_holder_release_dirs(struct bd_holder *bo)
-{
-	kobject_put(bo->hdir);
-	kobject_put(bo->sdev);
-	kobject_put(bo->hdev);
-	kobject_put(bo->sdir);
-}
-
-static struct bd_holder *alloc_bd_holder(struct kobject *kobj)
-{
-	struct bd_holder *bo;
-
-	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
-	if (!bo)
-		return NULL;
-
-	bo->count = 1;
-	bo->sdir = kobj;
-
-	return bo;
-}
-
-static void free_bd_holder(struct bd_holder *bo)
-{
-	kfree(bo);
-}
-
-/**
- * find_bd_holder - find matching struct bd_holder from the block device
- *
- * @bdev:	struct block device to be searched
- * @bo:		target struct bd_holder
- *
- * Returns matching entry with @bo in @bdev->bd_holder_list.
- * If found, increment the reference count and return the pointer.
- * If not found, returns NULL.
- */
-static struct bd_holder *find_bd_holder(struct block_device *bdev,
-					struct bd_holder *bo)
-{
-	struct bd_holder *tmp;
-
-	list_for_each_entry(tmp, &bdev->bd_holder_list, list)
-		if (tmp->sdir == bo->sdir) {
-			tmp->count++;
-			return tmp;
-		}
-
-	return NULL;
-}
-
 /**
 /**
- * add_bd_holder - create sysfs symlinks for bd_claim() relationship
- *
- * @bdev:	block device to be bd_claimed
- * @bo:		preallocated and initialized by alloc_bd_holder()
+ * bd_link_disk_holder - create symlinks between holding disk and slave bdev
+ * @bdev: the claimed slave bdev
+ * @disk: the holding disk
  *
  *
- * Add @bo to @bdev->bd_holder_list, create symlinks.
- *
- * Returns 0 if symlinks are created.
- * Returns -ve if something fails.
- */
-static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo)
-{
-	int err;
-
-	if (!bo)
-		return -EINVAL;
-
-	if (!bd_holder_grab_dirs(bdev, bo))
-		return -EBUSY;
-
-	err = add_symlink(bo->sdir, bo->sdev);
-	if (err)
-		return err;
-
-	err = add_symlink(bo->hdir, bo->hdev);
-	if (err) {
-		del_symlink(bo->sdir, bo->sdev);
-		return err;
-	}
-
-	list_add_tail(&bo->list, &bdev->bd_holder_list);
-	return 0;
-}
-
-/**
- * del_bd_holder - delete sysfs symlinks for bd_claim() relationship
+ * This functions creates the following sysfs symlinks.
  *
  *
- * @bdev:	block device to be bd_claimed
- * @kobj:	holder's kobject
+ * - from "slaves" directory of the holder @disk to the claimed @bdev
+ * - from "holders" directory of the @bdev to the holder @disk
  *
  *
- * If there is matching entry with @kobj in @bdev->bd_holder_list
- * and no other bd_claim() from the same kobject,
- * remove the struct bd_holder from the list, delete symlinks for it.
+ * For example, if /dev/dm-0 maps to /dev/sda and disk for dm-0 is
+ * passed to bd_link_disk_holder(), then:
  *
  *
- * Returns a pointer to the struct bd_holder when it's removed from the list
- * and ready to be freed.
- * Returns NULL if matching claim isn't found or there is other bd_claim()
- * by the same kobject.
- */
-static struct bd_holder *del_bd_holder(struct block_device *bdev,
-					struct kobject *kobj)
-{
-	struct bd_holder *bo;
-
-	list_for_each_entry(bo, &bdev->bd_holder_list, list) {
-		if (bo->sdir == kobj) {
-			bo->count--;
-			BUG_ON(bo->count < 0);
-			if (!bo->count) {
-				list_del(&bo->list);
-				del_symlink(bo->sdir, bo->sdev);
-				del_symlink(bo->hdir, bo->hdev);
-				bd_holder_release_dirs(bo);
-				return bo;
-			}
-			break;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * bd_claim_by_kobject - bd_claim() with additional kobject signature
+ *   /sys/block/dm-0/slaves/sda --> /sys/block/sda
+ *   /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
  *
  *
- * @bdev:	block device to be claimed
- * @holder:	holder's signature
- * @kobj:	holder's kobject
+ * The caller must have claimed @bdev before calling this function and
+ * ensure that both @bdev and @disk are valid during the creation and
+ * lifetime of these symlinks.
  *
  *
- * Do bd_claim() and if it succeeds, create sysfs symlinks between
- * the bdev and the holder's kobject.
- * Use bd_release_from_kobject() when relesing the claimed bdev.
+ * CONTEXT:
+ * Might sleep.
  *
  *
- * Returns 0 on success. (same as bd_claim())
- * Returns errno on failure.
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
  */
-static int bd_claim_by_kobject(struct block_device *bdev, void *holder,
-				struct kobject *kobj)
+int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
 {
 {
-	int err;
-	struct bd_holder *bo, *found;
-
-	if (!kobj)
-		return -EINVAL;
-
-	bo = alloc_bd_holder(kobj);
-	if (!bo)
-		return -ENOMEM;
+	int ret = 0;
 
 
 	mutex_lock(&bdev->bd_mutex);
 	mutex_lock(&bdev->bd_mutex);
 
 
-	err = bd_claim(bdev, holder);
-	if (err)
-		goto fail;
+	WARN_ON_ONCE(!bdev->bd_holder || bdev->bd_holder_disk);
 
 
-	found = find_bd_holder(bdev, bo);
-	if (found)
-		goto fail;
+	/* FIXME: remove the following once add_disk() handles errors */
+	if (WARN_ON(!disk->slave_dir || !bdev->bd_part->holder_dir))
+		goto out_unlock;
 
 
-	err = add_bd_holder(bdev, bo);
-	if (err)
-		bd_release(bdev);
-	else
-		bo = NULL;
-fail:
-	mutex_unlock(&bdev->bd_mutex);
-	free_bd_holder(bo);
-	return err;
-}
+	ret = add_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
+	if (ret)
+		goto out_unlock;
 
 
-/**
- * bd_release_from_kobject - bd_release() with additional kobject signature
- *
- * @bdev:	block device to be released
- * @kobj:	holder's kobject
- *
- * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject().
- */
-static void bd_release_from_kobject(struct block_device *bdev,
-					struct kobject *kobj)
-{
-	if (!kobj)
-		return;
+	ret = add_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj);
+	if (ret) {
+		del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
+		goto out_unlock;
+	}
 
 
-	mutex_lock(&bdev->bd_mutex);
-	bd_release(bdev);
-	free_bd_holder(del_bd_holder(bdev, kobj));
+	bdev->bd_holder_disk = disk;
+out_unlock:
 	mutex_unlock(&bdev->bd_mutex);
 	mutex_unlock(&bdev->bd_mutex);
+	return ret;
 }
 }
+EXPORT_SYMBOL_GPL(bd_link_disk_holder);
 
 
-/**
- * bd_claim_by_disk - wrapper function for bd_claim_by_kobject()
- *
- * @bdev:	block device to be claimed
- * @holder:	holder's signature
- * @disk:	holder's gendisk
- *
- * Call bd_claim_by_kobject() with getting @disk->slave_dir.
- */
-int bd_claim_by_disk(struct block_device *bdev, void *holder,
-			struct gendisk *disk)
+static void bd_unlink_disk_holder(struct block_device *bdev)
 {
 {
-	return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir));
-}
-EXPORT_SYMBOL_GPL(bd_claim_by_disk);
+	struct gendisk *disk = bdev->bd_holder_disk;
 
 
-/**
- * bd_release_from_disk - wrapper function for bd_release_from_kobject()
- *
- * @bdev:	block device to be claimed
- * @disk:	holder's gendisk
- *
- * Call bd_release_from_kobject() and put @disk->slave_dir.
- */
-void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk)
-{
-	bd_release_from_kobject(bdev, disk->slave_dir);
-	kobject_put(disk->slave_dir);
-}
-EXPORT_SYMBOL_GPL(bd_release_from_disk);
-#endif
+	bdev->bd_holder_disk = NULL;
+	if (!disk)
+		return;
 
 
-/*
- * Tries to open block device by device number.  Use it ONLY if you
- * really do not have anything better - i.e. when you are behind a
- * truly sucky interface and all you are given is a device number.  _Never_
- * to be used for internal purposes.  If you ever need it - reconsider
- * your API.
- */
-struct block_device *open_by_devnum(dev_t dev, fmode_t mode)
-{
-	struct block_device *bdev = bdget(dev);
-	int err = -ENOMEM;
-	if (bdev)
-		err = blkdev_get(bdev, mode);
-	return err ? ERR_PTR(err) : bdev;
+	del_symlink(disk->slave_dir, &part_to_dev(bdev->bd_part)->kobj);
+	del_symlink(bdev->bd_part->holder_dir, &disk_to_dev(disk)->kobj);
 }
 }
-
-EXPORT_SYMBOL(open_by_devnum);
+#else
+static inline void bd_unlink_disk_holder(struct block_device *bdev)
+{ }
+#endif
 
 
 /**
 /**
  * flush_disk - invalidates all buffer-cache entries on a disk
  * flush_disk - invalidates all buffer-cache entries on a disk
@@ -1469,17 +1114,156 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 	return ret;
 	return ret;
 }
 }
 
 
-int blkdev_get(struct block_device *bdev, fmode_t mode)
+/**
+ * blkdev_get - open a block device
+ * @bdev: block_device to open
+ * @mode: FMODE_* mask
+ * @holder: exclusive holder identifier
+ *
+ * Open @bdev with @mode.  If @mode includes %FMODE_EXCL, @bdev is
+ * open with exclusive access.  Specifying %FMODE_EXCL with %NULL
+ * @holder is invalid.  Exclusive opens may nest for the same @holder.
+ *
+ * On success, the reference count of @bdev is unchanged.  On failure,
+ * @bdev is put.
+ *
+ * CONTEXT:
+ * Might sleep.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
 {
 {
-	return __blkdev_get(bdev, mode, 0);
+	struct block_device *whole = NULL;
+	int res;
+
+	WARN_ON_ONCE((mode & FMODE_EXCL) && !holder);
+
+	if ((mode & FMODE_EXCL) && holder) {
+		whole = bd_start_claiming(bdev, holder);
+		if (IS_ERR(whole)) {
+			bdput(bdev);
+			return PTR_ERR(whole);
+		}
+	}
+
+	res = __blkdev_get(bdev, mode, 0);
+
+	/* __blkdev_get() may alter read only status, check it afterwards */
+	if (!res && (mode & FMODE_WRITE) && bdev_read_only(bdev)) {
+		__blkdev_put(bdev, mode, 0);
+		res = -EACCES;
+	}
+
+	if (whole) {
+		/* finish claiming */
+		spin_lock(&bdev_lock);
+
+		if (res == 0) {
+			BUG_ON(!bd_may_claim(bdev, whole, holder));
+			/*
+			 * Note that for a whole device bd_holders
+			 * will be incremented twice, and bd_holder
+			 * will be set to bd_may_claim before being
+			 * set to holder
+			 */
+			whole->bd_holders++;
+			whole->bd_holder = bd_may_claim;
+			bdev->bd_holders++;
+			bdev->bd_holder = holder;
+		}
+
+		/* tell others that we're done */
+		BUG_ON(whole->bd_claiming != holder);
+		whole->bd_claiming = NULL;
+		wake_up_bit(&whole->bd_claiming, 0);
+
+		spin_unlock(&bdev_lock);
+		bdput(whole);
+	}
+
+	return res;
 }
 }
 EXPORT_SYMBOL(blkdev_get);
 EXPORT_SYMBOL(blkdev_get);
 
 
+/**
+ * blkdev_get_by_path - open a block device by name
+ * @path: path to the block device to open
+ * @mode: FMODE_* mask
+ * @holder: exclusive holder identifier
+ *
+ * Open the blockdevice described by the device file at @path.  @mode
+ * and @holder are identical to blkdev_get().
+ *
+ * On success, the returned block_device has reference count of one.
+ *
+ * CONTEXT:
+ * Might sleep.
+ *
+ * RETURNS:
+ * Pointer to block_device on success, ERR_PTR(-errno) on failure.
+ */
+struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
+					void *holder)
+{
+	struct block_device *bdev;
+	int err;
+
+	bdev = lookup_bdev(path);
+	if (IS_ERR(bdev))
+		return bdev;
+
+	err = blkdev_get(bdev, mode, holder);
+	if (err)
+		return ERR_PTR(err);
+
+	return bdev;
+}
+EXPORT_SYMBOL(blkdev_get_by_path);
+
+/**
+ * blkdev_get_by_dev - open a block device by device number
+ * @dev: device number of block device to open
+ * @mode: FMODE_* mask
+ * @holder: exclusive holder identifier
+ *
+ * Open the blockdevice described by device number @dev.  @mode and
+ * @holder are identical to blkdev_get().
+ *
+ * Use it ONLY if you really do not have anything better - i.e. when
+ * you are behind a truly sucky interface and all you are given is a
+ * device number.  _Never_ to be used for internal purposes.  If you
+ * ever need it - reconsider your API.
+ *
+ * On success, the returned block_device has reference count of one.
+ *
+ * CONTEXT:
+ * Might sleep.
+ *
+ * RETURNS:
+ * Pointer to block_device on success, ERR_PTR(-errno) on failure.
+ */
+struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
+{
+	struct block_device *bdev;
+	int err;
+
+	bdev = bdget(dev);
+	if (!bdev)
+		return ERR_PTR(-ENOMEM);
+
+	err = blkdev_get(bdev, mode, holder);
+	if (err)
+		return ERR_PTR(err);
+
+	return bdev;
+}
+EXPORT_SYMBOL(blkdev_get_by_dev);
+
 static int blkdev_open(struct inode * inode, struct file * filp)
 static int blkdev_open(struct inode * inode, struct file * filp)
 {
 {
-	struct block_device *whole = NULL;
 	struct block_device *bdev;
 	struct block_device *bdev;
-	int res;
 
 
 	/*
 	/*
 	 * Preserve backwards compatibility and allow large file access
 	 * Preserve backwards compatibility and allow large file access
@@ -1500,26 +1284,9 @@ static int blkdev_open(struct inode * inode, struct file * filp)
 	if (bdev == NULL)
 	if (bdev == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	if (filp->f_mode & FMODE_EXCL) {
-		whole = bd_start_claiming(bdev, filp);
-		if (IS_ERR(whole)) {
-			bdput(bdev);
-			return PTR_ERR(whole);
-		}
-	}
-
 	filp->f_mapping = bdev->bd_inode->i_mapping;
 	filp->f_mapping = bdev->bd_inode->i_mapping;
 
 
-	res = blkdev_get(bdev, filp->f_mode);
-
-	if (whole) {
-		if (res == 0)
-			bd_finish_claiming(bdev, whole, filp);
-		else
-			bd_abort_claiming(whole, filp);
-	}
-
-	return res;
+	return blkdev_get(bdev, filp->f_mode, filp);
 }
 }
 
 
 static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
@@ -1533,6 +1300,7 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 		bdev->bd_part_count--;
 		bdev->bd_part_count--;
 
 
 	if (!--bdev->bd_openers) {
 	if (!--bdev->bd_openers) {
+		WARN_ON_ONCE(bdev->bd_holders);
 		sync_blockdev(bdev);
 		sync_blockdev(bdev);
 		kill_bdev(bdev);
 		kill_bdev(bdev);
 	}
 	}
@@ -1563,6 +1331,34 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 
 
 int blkdev_put(struct block_device *bdev, fmode_t mode)
 int blkdev_put(struct block_device *bdev, fmode_t mode)
 {
 {
+	if (mode & FMODE_EXCL) {
+		bool bdev_free;
+
+		/*
+		 * Release a claim on the device.  The holder fields
+		 * are protected with bdev_lock.  bd_mutex is to
+		 * synchronize disk_holder unlinking.
+		 */
+		mutex_lock(&bdev->bd_mutex);
+		spin_lock(&bdev_lock);
+
+		WARN_ON_ONCE(--bdev->bd_holders < 0);
+		WARN_ON_ONCE(--bdev->bd_contains->bd_holders < 0);
+
+		/* bd_contains might point to self, check in a separate step */
+		if ((bdev_free = !bdev->bd_holders))
+			bdev->bd_holder = NULL;
+		if (!bdev->bd_contains->bd_holders)
+			bdev->bd_contains->bd_holder = NULL;
+
+		spin_unlock(&bdev_lock);
+
+		/* if this was the last claim, holder link should go too */
+		if (bdev_free)
+			bd_unlink_disk_holder(bdev);
+
+		mutex_unlock(&bdev->bd_mutex);
+	}
 	return __blkdev_put(bdev, mode, 0);
 	return __blkdev_put(bdev, mode, 0);
 }
 }
 EXPORT_SYMBOL(blkdev_put);
 EXPORT_SYMBOL(blkdev_put);
@@ -1570,8 +1366,7 @@ EXPORT_SYMBOL(blkdev_put);
 static int blkdev_close(struct inode * inode, struct file * filp)
 static int blkdev_close(struct inode * inode, struct file * filp)
 {
 {
 	struct block_device *bdev = I_BDEV(filp->f_mapping->host);
 	struct block_device *bdev = I_BDEV(filp->f_mapping->host);
-	if (bdev->bd_holder == filp)
-		bd_release(bdev);
+
 	return blkdev_put(bdev, filp->f_mode);
 	return blkdev_put(bdev, filp->f_mode);
 }
 }
 
 
@@ -1716,67 +1511,6 @@ fail:
 }
 }
 EXPORT_SYMBOL(lookup_bdev);
 EXPORT_SYMBOL(lookup_bdev);
 
 
-/**
- * open_bdev_exclusive  -  open a block device by name and set it up for use
- *
- * @path:	special file representing the block device
- * @mode:	FMODE_... combination to pass be used
- * @holder:	owner for exclusion
- *
- * Open the blockdevice described by the special file at @path, claim it
- * for the @holder.
- */
-struct block_device *open_bdev_exclusive(const char *path, fmode_t mode, void *holder)
-{
-	struct block_device *bdev, *whole;
-	int error;
-
-	bdev = lookup_bdev(path);
-	if (IS_ERR(bdev))
-		return bdev;
-
-	whole = bd_start_claiming(bdev, holder);
-	if (IS_ERR(whole)) {
-		bdput(bdev);
-		return whole;
-	}
-
-	error = blkdev_get(bdev, mode);
-	if (error)
-		goto out_abort_claiming;
-
-	error = -EACCES;
-	if ((mode & FMODE_WRITE) && bdev_read_only(bdev))
-		goto out_blkdev_put;
-
-	bd_finish_claiming(bdev, whole, holder);
-	return bdev;
-
-out_blkdev_put:
-	blkdev_put(bdev, mode);
-out_abort_claiming:
-	bd_abort_claiming(whole, holder);
-	return ERR_PTR(error);
-}
-
-EXPORT_SYMBOL(open_bdev_exclusive);
-
-/**
- * close_bdev_exclusive  -  close a blockdevice opened by open_bdev_exclusive()
- *
- * @bdev:	blockdevice to close
- * @mode:	mode, must match that used to open.
- *
- * This is the counterpart to open_bdev_exclusive().
- */
-void close_bdev_exclusive(struct block_device *bdev, fmode_t mode)
-{
-	bd_release(bdev);
-	blkdev_put(bdev, mode);
-}
-
-EXPORT_SYMBOL(close_bdev_exclusive);
-
 int __invalidate_device(struct block_device *bdev)
 int __invalidate_device(struct block_device *bdev)
 {
 {
 	struct super_block *sb = get_super(bdev);
 	struct super_block *sb = get_super(bdev);

+ 16 - 12
fs/btrfs/volumes.c

@@ -489,7 +489,7 @@ again:
 			continue;
 			continue;
 
 
 		if (device->bdev) {
 		if (device->bdev) {
-			close_bdev_exclusive(device->bdev, device->mode);
+			blkdev_put(device->bdev, device->mode);
 			device->bdev = NULL;
 			device->bdev = NULL;
 			fs_devices->open_devices--;
 			fs_devices->open_devices--;
 		}
 		}
@@ -523,7 +523,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 
 
 	list_for_each_entry(device, &fs_devices->devices, dev_list) {
 	list_for_each_entry(device, &fs_devices->devices, dev_list) {
 		if (device->bdev) {
 		if (device->bdev) {
-			close_bdev_exclusive(device->bdev, device->mode);
+			blkdev_put(device->bdev, device->mode);
 			fs_devices->open_devices--;
 			fs_devices->open_devices--;
 		}
 		}
 		if (device->writeable) {
 		if (device->writeable) {
@@ -580,13 +580,15 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 	int seeding = 1;
 	int seeding = 1;
 	int ret = 0;
 	int ret = 0;
 
 
+	flags |= FMODE_EXCL;
+
 	list_for_each_entry(device, head, dev_list) {
 	list_for_each_entry(device, head, dev_list) {
 		if (device->bdev)
 		if (device->bdev)
 			continue;
 			continue;
 		if (!device->name)
 		if (!device->name)
 			continue;
 			continue;
 
 
-		bdev = open_bdev_exclusive(device->name, flags, holder);
+		bdev = blkdev_get_by_path(device->name, flags, holder);
 		if (IS_ERR(bdev)) {
 		if (IS_ERR(bdev)) {
 			printk(KERN_INFO "open %s failed\n", device->name);
 			printk(KERN_INFO "open %s failed\n", device->name);
 			goto error;
 			goto error;
@@ -638,7 +640,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 error_brelse:
 error_brelse:
 		brelse(bh);
 		brelse(bh);
 error_close:
 error_close:
-		close_bdev_exclusive(bdev, FMODE_READ);
+		blkdev_put(bdev, flags);
 error:
 error:
 		continue;
 		continue;
 	}
 	}
@@ -684,7 +686,8 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 
 
 	mutex_lock(&uuid_mutex);
 	mutex_lock(&uuid_mutex);
 
 
-	bdev = open_bdev_exclusive(path, flags, holder);
+	flags |= FMODE_EXCL;
+	bdev = blkdev_get_by_path(path, flags, holder);
 
 
 	if (IS_ERR(bdev)) {
 	if (IS_ERR(bdev)) {
 		ret = PTR_ERR(bdev);
 		ret = PTR_ERR(bdev);
@@ -716,7 +719,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 
 
 	brelse(bh);
 	brelse(bh);
 error_close:
 error_close:
-	close_bdev_exclusive(bdev, flags);
+	blkdev_put(bdev, flags);
 error:
 error:
 	mutex_unlock(&uuid_mutex);
 	mutex_unlock(&uuid_mutex);
 	return ret;
 	return ret;
@@ -1179,8 +1182,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 			goto out;
 			goto out;
 		}
 		}
 	} else {
 	} else {
-		bdev = open_bdev_exclusive(device_path, FMODE_READ,
-				      root->fs_info->bdev_holder);
+		bdev = blkdev_get_by_path(device_path, FMODE_READ | FMODE_EXCL,
+					  root->fs_info->bdev_holder);
 		if (IS_ERR(bdev)) {
 		if (IS_ERR(bdev)) {
 			ret = PTR_ERR(bdev);
 			ret = PTR_ERR(bdev);
 			goto out;
 			goto out;
@@ -1244,7 +1247,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
 		root->fs_info->fs_devices->latest_bdev = next_device->bdev;
 		root->fs_info->fs_devices->latest_bdev = next_device->bdev;
 
 
 	if (device->bdev) {
 	if (device->bdev) {
-		close_bdev_exclusive(device->bdev, device->mode);
+		blkdev_put(device->bdev, device->mode);
 		device->bdev = NULL;
 		device->bdev = NULL;
 		device->fs_devices->open_devices--;
 		device->fs_devices->open_devices--;
 	}
 	}
@@ -1287,7 +1290,7 @@ error_brelse:
 	brelse(bh);
 	brelse(bh);
 error_close:
 error_close:
 	if (bdev)
 	if (bdev)
-		close_bdev_exclusive(bdev, FMODE_READ);
+		blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
 out:
 out:
 	mutex_unlock(&root->fs_info->volume_mutex);
 	mutex_unlock(&root->fs_info->volume_mutex);
 	mutex_unlock(&uuid_mutex);
 	mutex_unlock(&uuid_mutex);
@@ -1439,7 +1442,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 	if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding)
 	if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder);
+	bdev = blkdev_get_by_path(device_path, FMODE_EXCL,
+				  root->fs_info->bdev_holder);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
 		return PTR_ERR(bdev);
 
 
@@ -1565,7 +1569,7 @@ out:
 	mutex_unlock(&root->fs_info->volume_mutex);
 	mutex_unlock(&root->fs_info->volume_mutex);
 	return ret;
 	return ret;
 error:
 error:
-	close_bdev_exclusive(bdev, 0);
+	blkdev_put(bdev, FMODE_EXCL);
 	if (seeding_dev) {
 	if (seeding_dev) {
 		mutex_unlock(&uuid_mutex);
 		mutex_unlock(&uuid_mutex);
 		up_write(&sb->s_umount);
 		up_write(&sb->s_umount);

+ 1 - 1
fs/btrfs/volumes.h

@@ -49,7 +49,7 @@ struct btrfs_device {
 
 
 	struct block_device *bdev;
 	struct block_device *bdev;
 
 
-	/* the mode sent to open_bdev_exclusive */
+	/* the mode sent to blkdev_get */
 	fmode_t mode;
 	fmode_t mode;
 
 
 	char *name;
 	char *name;

+ 2 - 10
fs/ext3/super.c

@@ -347,7 +347,7 @@ static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb)
 	struct block_device *bdev;
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 	char b[BDEVNAME_SIZE];
 
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		goto fail;
 		goto fail;
 	return bdev;
 	return bdev;
@@ -364,8 +364,7 @@ fail:
  */
  */
 static int ext3_blkdev_put(struct block_device *bdev)
 static int ext3_blkdev_put(struct block_device *bdev)
 {
 {
-	bd_release(bdev);
-	return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 }
 
 
 static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
 static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
@@ -2136,13 +2135,6 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
 	if (bdev == NULL)
 	if (bdev == NULL)
 		return NULL;
 		return NULL;
 
 
-	if (bd_claim(bdev, sb)) {
-		ext3_msg(sb, KERN_ERR,
-			"error: failed to claim external journal device");
-		blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
-		return NULL;
-	}
-
 	blocksize = sb->s_blocksize;
 	blocksize = sb->s_blocksize;
 	hblock = bdev_logical_block_size(bdev);
 	hblock = bdev_logical_block_size(bdev);
 	if (blocksize < hblock) {
 	if (blocksize < hblock) {

+ 2 - 10
fs/ext4/super.c

@@ -647,7 +647,7 @@ static struct block_device *ext4_blkdev_get(dev_t dev, struct super_block *sb)
 	struct block_device *bdev;
 	struct block_device *bdev;
 	char b[BDEVNAME_SIZE];
 	char b[BDEVNAME_SIZE];
 
 
-	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
+	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		goto fail;
 		goto fail;
 	return bdev;
 	return bdev;
@@ -663,8 +663,7 @@ fail:
  */
  */
 static int ext4_blkdev_put(struct block_device *bdev)
 static int ext4_blkdev_put(struct block_device *bdev)
 {
 {
-	bd_release(bdev);
-	return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 }
 
 
 static int ext4_blkdev_remove(struct ext4_sb_info *sbi)
 static int ext4_blkdev_remove(struct ext4_sb_info *sbi)
@@ -3758,13 +3757,6 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
 	if (bdev == NULL)
 	if (bdev == NULL)
 		return NULL;
 		return NULL;
 
 
-	if (bd_claim(bdev, sb)) {
-		ext4_msg(sb, KERN_ERR,
-			"failed to claim external journal device");
-		blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
-		return NULL;
-	}
-
 	blocksize = sb->s_blocksize;
 	blocksize = sb->s_blocksize;
 	hblock = bdev_logical_block_size(bdev);
 	hblock = bdev_logical_block_size(bdev);
 	if (blocksize < hblock) {
 	if (blocksize < hblock) {

+ 4 - 42
fs/gfs2/export.c

@@ -138,10 +138,8 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
 				      struct gfs2_inum_host *inum)
 				      struct gfs2_inum_host *inum)
 {
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	struct gfs2_sbd *sdp = sb->s_fs_info;
-	struct gfs2_holder i_gh;
 	struct inode *inode;
 	struct inode *inode;
 	struct dentry *dentry;
 	struct dentry *dentry;
-	int error;
 
 
 	inode = gfs2_ilookup(sb, inum->no_addr);
 	inode = gfs2_ilookup(sb, inum->no_addr);
 	if (inode) {
 	if (inode) {
@@ -152,52 +150,16 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb,
 		goto out_inode;
 		goto out_inode;
 	}
 	}
 
 
-	error = gfs2_glock_nq_num(sdp, inum->no_addr, &gfs2_inode_glops,
-				  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-	if (error)
-		return ERR_PTR(error);
-
-	error = gfs2_check_blk_type(sdp, inum->no_addr, GFS2_BLKST_DINODE);
-	if (error)
-		goto fail;
-
-	inode = gfs2_inode_lookup(sb, DT_UNKNOWN, inum->no_addr, 0);
-	if (IS_ERR(inode)) {
-		error = PTR_ERR(inode);
-		goto fail;
-	}
-
-	error = gfs2_inode_refresh(GFS2_I(inode));
-	if (error) {
-		iput(inode);
-		goto fail;
-	}
-
-	/* Pick up the works we bypass in gfs2_inode_lookup */
-	if (inode->i_state & I_NEW) 
-		gfs2_set_iop(inode);
-
-	if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
-		iput(inode);
-		goto fail;
-	}
-
-	error = -EIO;
-	if (GFS2_I(inode)->i_diskflags & GFS2_DIF_SYSTEM) {
-		iput(inode);
-		goto fail;
-	}
-
-	gfs2_glock_dq_uninit(&i_gh);
+	inode = gfs2_lookup_by_inum(sdp, inum->no_addr, &inum->no_formal_ino,
+				    GFS2_BLKST_DINODE);
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
 
 
 out_inode:
 out_inode:
 	dentry = d_obtain_alias(inode);
 	dentry = d_obtain_alias(inode);
 	if (!IS_ERR(dentry))
 	if (!IS_ERR(dentry))
 		dentry->d_op = &gfs2_dops;
 		dentry->d_op = &gfs2_dops;
 	return dentry;
 	return dentry;
-fail:
-	gfs2_glock_dq_uninit(&i_gh);
-	return ERR_PTR(error);
 }
 }
 
 
 static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
 static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid,

+ 10 - 11
fs/gfs2/glock.c

@@ -686,21 +686,20 @@ static void delete_work_func(struct work_struct *work)
 {
 {
 	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
 	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct gfs2_inode *ip = NULL;
+	struct gfs2_inode *ip;
 	struct inode *inode;
 	struct inode *inode;
-	u64 no_addr = 0;
+	u64 no_addr = gl->gl_name.ln_number;
+
+	ip = gl->gl_object;
+	/* Note: Unsafe to dereference ip as we don't hold right refs/locks */
 
 
-	spin_lock(&gl->gl_spin);
-	ip = (struct gfs2_inode *)gl->gl_object;
 	if (ip)
 	if (ip)
-		no_addr = ip->i_no_addr;
-	spin_unlock(&gl->gl_spin);
-	if (ip) {
 		inode = gfs2_ilookup(sdp->sd_vfs, no_addr);
 		inode = gfs2_ilookup(sdp->sd_vfs, no_addr);
-		if (inode) {
-			d_prune_aliases(inode);
-			iput(inode);
-		}
+	else
+		inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED);
+	if (inode && !IS_ERR(inode)) {
+		d_prune_aliases(inode);
+		iput(inode);
 	}
 	}
 	gfs2_glock_put(gl);
 	gfs2_glock_put(gl);
 }
 }

+ 35 - 117
fs/gfs2/inode.c

@@ -73,49 +73,6 @@ static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
 	return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
 	return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
 }
 }
 
 
-struct gfs2_skip_data {
-	u64	no_addr;
-	int	skipped;
-};
-
-static int iget_skip_test(struct inode *inode, void *opaque)
-{
-	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_skip_data *data = opaque;
-
-	if (ip->i_no_addr == data->no_addr) {
-		if (inode->i_state & (I_FREEING|I_WILL_FREE)){
-			data->skipped = 1;
-			return 0;
-		}
-		return 1;
-	}
-	return 0;
-}
-
-static int iget_skip_set(struct inode *inode, void *opaque)
-{
-	struct gfs2_inode *ip = GFS2_I(inode);
-	struct gfs2_skip_data *data = opaque;
-
-	if (data->skipped)
-		return 1;
-	inode->i_ino = (unsigned long)(data->no_addr);
-	ip->i_no_addr = data->no_addr;
-	return 0;
-}
-
-static struct inode *gfs2_iget_skip(struct super_block *sb,
-				    u64 no_addr)
-{
-	struct gfs2_skip_data data;
-	unsigned long hash = (unsigned long)no_addr;
-
-	data.no_addr = no_addr;
-	data.skipped = 0;
-	return iget5_locked(sb, hash, iget_skip_test, iget_skip_set, &data);
-}
-
 /**
 /**
  * GFS2 lookup code fills in vfs inode contents based on info obtained
  * GFS2 lookup code fills in vfs inode contents based on info obtained
  * from directory entry inside gfs2_inode_lookup(). This has caused issues
  * from directory entry inside gfs2_inode_lookup(). This has caused issues
@@ -243,93 +200,54 @@ fail:
 	return ERR_PTR(error);
 	return ERR_PTR(error);
 }
 }
 
 
-/**
- * gfs2_process_unlinked_inode - Lookup an unlinked inode for reclamation
- *                               and try to reclaim it by doing iput.
- *
- * This function assumes no rgrp locks are currently held.
- *
- * @sb: The super block
- * no_addr: The inode number
- *
- */
-
-void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr)
+struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
+				  u64 *no_formal_ino, unsigned int blktype)
 {
 {
-	struct gfs2_sbd *sdp;
-	struct gfs2_inode *ip;
-	struct gfs2_glock *io_gl = NULL;
-	int error;
-	struct gfs2_holder gh;
+	struct super_block *sb = sdp->sd_vfs;
+	struct gfs2_holder i_gh;
 	struct inode *inode;
 	struct inode *inode;
+	int error;
 
 
-	inode = gfs2_iget_skip(sb, no_addr);
-
-	if (!inode)
-		return;
-
-	/* If it's not a new inode, someone's using it, so leave it alone. */
-	if (!(inode->i_state & I_NEW)) {
-		iput(inode);
-		return;
-	}
-
-	ip = GFS2_I(inode);
-	sdp = GFS2_SB(inode);
-	ip->i_no_formal_ino = -1;
+	error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops,
+				  LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+	if (error)
+		return ERR_PTR(error);
 
 
-	error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
-	if (unlikely(error))
+	error = gfs2_check_blk_type(sdp, no_addr, blktype);
+	if (error)
 		goto fail;
 		goto fail;
-	ip->i_gl->gl_object = ip;
 
 
-	error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
-	if (unlikely(error))
-		goto fail_put;
-
-	set_bit(GIF_INVALID, &ip->i_flags);
-	error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, LM_FLAG_TRY | GL_EXACT,
-				   &ip->i_iopen_gh);
-	if (unlikely(error))
-		goto fail_iopen;
+	inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0);
+	if (IS_ERR(inode))
+		goto fail;
 
 
-	ip->i_iopen_gh.gh_gl->gl_object = ip;
-	gfs2_glock_put(io_gl);
-	io_gl = NULL;
+	error = gfs2_inode_refresh(GFS2_I(inode));
+	if (error)
+		goto fail_iput;
 
 
-	inode->i_mode = DT2IF(DT_UNKNOWN);
+	/* Pick up the works we bypass in gfs2_inode_lookup */
+	if (inode->i_state & I_NEW) 
+		gfs2_set_iop(inode);
 
 
-	/*
-	 * We must read the inode in order to work out its type in
-	 * this case. Note that this doesn't happen often as we normally
-	 * know the type beforehand. This code path only occurs during
-	 * unlinked inode recovery (where it is safe to do this glock,
-	 * which is not true in the general case).
-	 */
-	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY,
-				   &gh);
-	if (unlikely(error))
-		goto fail_glock;
+	/* Two extra checks for NFS only */
+	if (no_formal_ino) {
+		error = -ESTALE;
+		if (GFS2_I(inode)->i_no_formal_ino != *no_formal_ino)
+			goto fail_iput;
 
 
-	/* Inode is now uptodate */
-	gfs2_glock_dq_uninit(&gh);
-	gfs2_set_iop(inode);
+		error = -EIO;
+		if (GFS2_I(inode)->i_diskflags & GFS2_DIF_SYSTEM)
+			goto fail_iput;
 
 
-	/* The iput will cause it to be deleted. */
-	iput(inode);
-	return;
+		error = 0;
+	}
 
 
-fail_glock:
-	gfs2_glock_dq(&ip->i_iopen_gh);
-fail_iopen:
-	if (io_gl)
-		gfs2_glock_put(io_gl);
-fail_put:
-	ip->i_gl->gl_object = NULL;
-	gfs2_glock_put(ip->i_gl);
 fail:
 fail:
-	iget_failed(inode);
-	return;
+	gfs2_glock_dq_uninit(&i_gh);
+	return error ? ERR_PTR(error) : inode;
+fail_iput:
+	iput(inode);
+	goto fail;
 }
 }
 
 
 static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
 static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)

+ 3 - 1
fs/gfs2/inode.h

@@ -99,7 +99,9 @@ err:
 extern void gfs2_set_iop(struct inode *inode);
 extern void gfs2_set_iop(struct inode *inode);
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
 				       u64 no_addr, u64 no_formal_ino);
 				       u64 no_addr, u64 no_formal_ino);
-extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr);
+extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
+					 u64 *no_formal_ino,
+					 unsigned int blktype);
 extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 
 
 extern int gfs2_inode_refresh(struct gfs2_inode *ip);
 extern int gfs2_inode_refresh(struct gfs2_inode *ip);

+ 4 - 4
fs/gfs2/ops_fstype.c

@@ -1268,7 +1268,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
 {
 {
 	struct block_device *bdev;
 	struct block_device *bdev;
 	struct super_block *s;
 	struct super_block *s;
-	fmode_t mode = FMODE_READ;
+	fmode_t mode = FMODE_READ | FMODE_EXCL;
 	int error;
 	int error;
 	struct gfs2_args args;
 	struct gfs2_args args;
 	struct gfs2_sbd *sdp;
 	struct gfs2_sbd *sdp;
@@ -1276,7 +1276,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
 	if (!(flags & MS_RDONLY))
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
 		mode |= FMODE_WRITE;
 
 
-	bdev = open_bdev_exclusive(dev_name, mode, fs_type);
+	bdev = blkdev_get_by_path(dev_name, mode, fs_type);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		return ERR_CAST(bdev);
 		return ERR_CAST(bdev);
 
 
@@ -1298,7 +1298,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
 		goto error_bdev;
 		goto error_bdev;
 
 
 	if (s->s_root)
 	if (s->s_root)
-		close_bdev_exclusive(bdev, mode);
+		blkdev_put(bdev, mode);
 
 
 	memset(&args, 0, sizeof(args));
 	memset(&args, 0, sizeof(args));
 	args.ar_quota = GFS2_QUOTA_DEFAULT;
 	args.ar_quota = GFS2_QUOTA_DEFAULT;
@@ -1342,7 +1342,7 @@ error_super:
 	deactivate_locked_super(s);
 	deactivate_locked_super(s);
 	return ERR_PTR(error);
 	return ERR_PTR(error);
 error_bdev:
 error_bdev:
-	close_bdev_exclusive(bdev, mode);
+	blkdev_put(bdev, mode);
 	return ERR_PTR(error);
 	return ERR_PTR(error);
 }
 }
 
 

+ 46 - 45
fs/gfs2/rgrp.c

@@ -963,17 +963,18 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
  *          The inode, if one has been found, in inode.
  *          The inode, if one has been found, in inode.
  */
  */
 
 
-static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked,
-			   u64 skip)
+static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip)
 {
 {
 	u32 goal = 0, block;
 	u32 goal = 0, block;
 	u64 no_addr;
 	u64 no_addr;
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	struct gfs2_sbd *sdp = rgd->rd_sbd;
 	unsigned int n;
 	unsigned int n;
+	struct gfs2_glock *gl;
+	struct gfs2_inode *ip;
+	int error;
+	int found = 0;
 
 
-	for(;;) {
-		if (goal >= rgd->rd_data)
-			break;
+	while (goal < rgd->rd_data) {
 		down_write(&sdp->sd_log_flush_lock);
 		down_write(&sdp->sd_log_flush_lock);
 		n = 1;
 		n = 1;
 		block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
 		block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
@@ -990,11 +991,32 @@ static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked,
 		if (no_addr == skip)
 		if (no_addr == skip)
 			continue;
 			continue;
 		*last_unlinked = no_addr;
 		*last_unlinked = no_addr;
-		return no_addr;
+
+		error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &gl);
+		if (error)
+			continue;
+
+		/* If the inode is already in cache, we can ignore it here
+		 * because the existing inode disposal code will deal with
+		 * it when all refs have gone away. Accessing gl_object like
+		 * this is not safe in general. Here it is ok because we do
+		 * not dereference the pointer, and we only need an approx
+		 * answer to whether it is NULL or not.
+		 */
+		ip = gl->gl_object;
+
+		if (ip || queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0)
+			gfs2_glock_put(gl);
+		else
+			found++;
+
+		/* Limit reclaim to sensible number of tasks */
+		if (found > 2*NR_CPUS)
+			return;
 	}
 	}
 
 
 	rgd->rd_flags &= ~GFS2_RDF_CHECK;
 	rgd->rd_flags &= ~GFS2_RDF_CHECK;
-	return 0;
+	return;
 }
 }
 
 
 /**
 /**
@@ -1075,11 +1097,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
  * Try to acquire rgrp in way which avoids contending with others.
  * Try to acquire rgrp in way which avoids contending with others.
  *
  *
  * Returns: errno
  * Returns: errno
- *          unlinked: the block address of an unlinked block to be reclaimed
  */
  */
 
 
-static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
-			  u64 *last_unlinked)
+static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
 {
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd, *begin = NULL;
 	struct gfs2_rgrpd *rgd, *begin = NULL;
@@ -1089,7 +1109,6 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
 	int loops = 0;
 	int loops = 0;
 	int error, rg_locked;
 	int error, rg_locked;
 
 
-	*unlinked = 0;
 	rgd = gfs2_blk2rgrpd(sdp, ip->i_goal);
 	rgd = gfs2_blk2rgrpd(sdp, ip->i_goal);
 
 
 	while (rgd) {
 	while (rgd) {
@@ -1106,17 +1125,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
 		case 0:
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 			if (try_rgrp_fit(rgd, al))
 				goto out;
 				goto out;
-			/* If the rg came in already locked, there's no
-			   way we can recover from a failed try_rgrp_unlink
-			   because that would require an iput which can only
-			   happen after the rgrp is unlocked. */
-			if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK)
-				*unlinked = try_rgrp_unlink(rgd, last_unlinked,
-							   ip->i_no_addr);
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
 			if (!rg_locked)
 			if (!rg_locked)
 				gfs2_glock_dq_uninit(&al->al_rgd_gh);
 				gfs2_glock_dq_uninit(&al->al_rgd_gh);
-			if (*unlinked)
-				return -EAGAIN;
 			/* fall through */
 			/* fall through */
 		case GLR_TRYFAILED:
 		case GLR_TRYFAILED:
 			rgd = recent_rgrp_next(rgd);
 			rgd = recent_rgrp_next(rgd);
@@ -1145,13 +1157,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
 		case 0:
 		case 0:
 			if (try_rgrp_fit(rgd, al))
 			if (try_rgrp_fit(rgd, al))
 				goto out;
 				goto out;
-			if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK)
-				*unlinked = try_rgrp_unlink(rgd, last_unlinked,
-							    ip->i_no_addr);
+			if (rgd->rd_flags & GFS2_RDF_CHECK)
+				try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
 			if (!rg_locked)
 			if (!rg_locked)
 				gfs2_glock_dq_uninit(&al->al_rgd_gh);
 				gfs2_glock_dq_uninit(&al->al_rgd_gh);
-			if (*unlinked)
-				return -EAGAIN;
 			break;
 			break;
 
 
 		case GLR_TRYFAILED:
 		case GLR_TRYFAILED:
@@ -1204,12 +1213,12 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex,
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_alloc *al = ip->i_alloc;
 	struct gfs2_alloc *al = ip->i_alloc;
 	int error = 0;
 	int error = 0;
-	u64 last_unlinked = NO_BLOCK, unlinked;
+	u64 last_unlinked = NO_BLOCK;
+	int tries = 0;
 
 
 	if (gfs2_assert_warn(sdp, al->al_requested))
 	if (gfs2_assert_warn(sdp, al->al_requested))
 		return -EINVAL;
 		return -EINVAL;
 
 
-try_again:
 	if (hold_rindex) {
 	if (hold_rindex) {
 		/* We need to hold the rindex unless the inode we're using is
 		/* We need to hold the rindex unless the inode we're using is
 		   the rindex itself, in which case it's already held. */
 		   the rindex itself, in which case it's already held. */
@@ -1218,31 +1227,23 @@ try_again:
 		else if (!sdp->sd_rgrps) /* We may not have the rindex read
 		else if (!sdp->sd_rgrps) /* We may not have the rindex read
 					    in, so: */
 					    in, so: */
 			error = gfs2_ri_update_special(ip);
 			error = gfs2_ri_update_special(ip);
+		if (error)
+			return error;
 	}
 	}
 
 
-	if (error)
-		return error;
+	do {
+		error = get_local_rgrp(ip, &last_unlinked);
+		/* If there is no space, flushing the log may release some */
+		if (error)
+			gfs2_log_flush(sdp, NULL);
+	} while (error && tries++ < 3);
 
 
-	/* Find an rgrp suitable for allocation.  If it encounters any unlinked
-	   dinodes along the way, error will equal -EAGAIN and unlinked will
-	   contains it block address. We then need to look up that inode and
-	   try to free it, and try the allocation again. */
-	error = get_local_rgrp(ip, &unlinked, &last_unlinked);
 	if (error) {
 	if (error) {
 		if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
 		if (hold_rindex && ip != GFS2_I(sdp->sd_rindex))
 			gfs2_glock_dq_uninit(&al->al_ri_gh);
 			gfs2_glock_dq_uninit(&al->al_ri_gh);
-		if (error != -EAGAIN)
-			return error;
-
-		gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked);
-		/* regardless of whether or not gfs2_process_unlinked_inode
-		   was successful, we don't want to repeat it again. */
-		last_unlinked = unlinked;
-		gfs2_log_flush(sdp, NULL);
-		error = 0;
-
-		goto try_again;
+		return error;
 	}
 	}
+
 	/* no error, so we have the rgrp set in the inode's allocation. */
 	/* no error, so we have the rgrp set in the inode's allocation. */
 	al->al_file = file;
 	al->al_file = file;
 	al->al_line = line;
 	al->al_line = line;

+ 5 - 12
fs/jfs/jfs_logmgr.c

@@ -1120,16 +1120,13 @@ int lmLogOpen(struct super_block *sb)
 	 * file systems to log may have n-to-1 relationship;
 	 * file systems to log may have n-to-1 relationship;
 	 */
 	 */
 
 
-	bdev = open_by_devnum(sbi->logdev, FMODE_READ|FMODE_WRITE);
+	bdev = blkdev_get_by_dev(sbi->logdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				 log);
 	if (IS_ERR(bdev)) {
 	if (IS_ERR(bdev)) {
 		rc = -PTR_ERR(bdev);
 		rc = -PTR_ERR(bdev);
 		goto free;
 		goto free;
 	}
 	}
 
 
-	if ((rc = bd_claim(bdev, log))) {
-		goto close;
-	}
-
 	log->bdev = bdev;
 	log->bdev = bdev;
 	memcpy(log->uuid, sbi->loguuid, sizeof(log->uuid));
 	memcpy(log->uuid, sbi->loguuid, sizeof(log->uuid));
 
 
@@ -1137,7 +1134,7 @@ int lmLogOpen(struct super_block *sb)
 	 * initialize log:
 	 * initialize log:
 	 */
 	 */
 	if ((rc = lmLogInit(log)))
 	if ((rc = lmLogInit(log)))
-		goto unclaim;
+		goto close;
 
 
 	list_add(&log->journal_list, &jfs_external_logs);
 	list_add(&log->journal_list, &jfs_external_logs);
 
 
@@ -1163,11 +1160,8 @@ journal_found:
 	list_del(&log->journal_list);
 	list_del(&log->journal_list);
 	lbmLogShutdown(log);
 	lbmLogShutdown(log);
 
 
-      unclaim:
-	bd_release(bdev);
-
       close:		/* close external log device */
       close:		/* close external log device */
-	blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 
 
       free:		/* free log descriptor */
       free:		/* free log descriptor */
 	mutex_unlock(&jfs_log_mutex);
 	mutex_unlock(&jfs_log_mutex);
@@ -1512,8 +1506,7 @@ int lmLogClose(struct super_block *sb)
 	bdev = log->bdev;
 	bdev = log->bdev;
 	rc = lmLogShutdown(log);
 	rc = lmLogShutdown(log);
 
 
-	bd_release(bdev);
-	blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
+	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 
 
 	kfree(log);
 	kfree(log);
 
 

+ 4 - 3
fs/logfs/dev_bdev.c

@@ -300,7 +300,7 @@ static int bdev_write_sb(struct super_block *sb, struct page *page)
 
 
 static void bdev_put_device(struct logfs_super *s)
 static void bdev_put_device(struct logfs_super *s)
 {
 {
-	close_bdev_exclusive(s->s_bdev, FMODE_READ|FMODE_WRITE);
+	blkdev_put(s->s_bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 }
 
 
 static int bdev_can_write_buf(struct super_block *sb, u64 ofs)
 static int bdev_can_write_buf(struct super_block *sb, u64 ofs)
@@ -325,13 +325,14 @@ int logfs_get_sb_bdev(struct logfs_super *p, struct file_system_type *type,
 {
 {
 	struct block_device *bdev;
 	struct block_device *bdev;
 
 
-	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, type);
+	bdev = blkdev_get_by_path(devname, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				  type);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		return PTR_ERR(bdev);
 		return PTR_ERR(bdev);
 
 
 	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
 		int mtdnr = MINOR(bdev->bd_dev);
 		int mtdnr = MINOR(bdev->bd_dev);
-		close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
+		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 		return logfs_get_sb_mtd(p, mtdnr);
 		return logfs_get_sb_mtd(p, mtdnr);
 	}
 	}
 
 

+ 4 - 4
fs/nilfs2/super.c

@@ -1147,14 +1147,14 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
 {
 {
 	struct nilfs_super_data sd;
 	struct nilfs_super_data sd;
 	struct super_block *s;
 	struct super_block *s;
-	fmode_t mode = FMODE_READ;
+	fmode_t mode = FMODE_READ | FMODE_EXCL;
 	struct dentry *root_dentry;
 	struct dentry *root_dentry;
 	int err, s_new = false;
 	int err, s_new = false;
 
 
 	if (!(flags & MS_RDONLY))
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
 		mode |= FMODE_WRITE;
 
 
-	sd.bdev = open_bdev_exclusive(dev_name, mode, fs_type);
+	sd.bdev = blkdev_get_by_path(dev_name, mode, fs_type);
 	if (IS_ERR(sd.bdev))
 	if (IS_ERR(sd.bdev))
 		return ERR_CAST(sd.bdev);
 		return ERR_CAST(sd.bdev);
 
 
@@ -1233,7 +1233,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
 	}
 	}
 
 
 	if (!s_new)
 	if (!s_new)
-		close_bdev_exclusive(sd.bdev, mode);
+		blkdev_put(sd.bdev, mode);
 
 
 	return root_dentry;
 	return root_dentry;
 
 
@@ -1242,7 +1242,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
 
 
  failed:
  failed:
 	if (!s_new)
 	if (!s_new)
-		close_bdev_exclusive(sd.bdev, mode);
+		blkdev_put(sd.bdev, mode);
 	return ERR_PTR(err);
 	return ERR_PTR(err);
 }
 }
 
 

+ 1 - 1
fs/ocfs2/cluster/heartbeat.c

@@ -1674,7 +1674,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
 		goto out;
 		goto out;
 
 
 	reg->hr_bdev = I_BDEV(filp->f_mapping->host);
 	reg->hr_bdev = I_BDEV(filp->f_mapping->host);
-	ret = blkdev_get(reg->hr_bdev, FMODE_WRITE | FMODE_READ);
+	ret = blkdev_get(reg->hr_bdev, FMODE_WRITE | FMODE_READ, NULL);
 	if (ret) {
 	if (ret) {
 		reg->hr_bdev = NULL;
 		reg->hr_bdev = NULL;
 		goto out;
 		goto out;

+ 3 - 3
fs/ocfs2/ocfs2.h

@@ -159,7 +159,9 @@ struct ocfs2_lock_res {
 	char                     l_name[OCFS2_LOCK_ID_MAX_LEN];
 	char                     l_name[OCFS2_LOCK_ID_MAX_LEN];
 	unsigned int             l_ro_holders;
 	unsigned int             l_ro_holders;
 	unsigned int             l_ex_holders;
 	unsigned int             l_ex_holders;
-	unsigned char            l_level;
+	char			 l_level;
+	char			 l_requested;
+	char			 l_blocking;
 
 
 	/* Data packed - type enum ocfs2_lock_type */
 	/* Data packed - type enum ocfs2_lock_type */
 	unsigned char            l_type;
 	unsigned char            l_type;
@@ -169,8 +171,6 @@ struct ocfs2_lock_res {
 	unsigned char            l_action;
 	unsigned char            l_action;
 	/* Data packed - enum type ocfs2_unlock_action */
 	/* Data packed - enum type ocfs2_unlock_action */
 	unsigned char            l_unlock_action;
 	unsigned char            l_unlock_action;
-	unsigned char            l_requested;
-	unsigned char            l_blocking;
 	unsigned int             l_pending_gen;
 	unsigned int             l_pending_gen;
 
 
 	spinlock_t               l_lock;
 	spinlock_t               l_lock;

+ 10 - 1
fs/partitions/check.c

@@ -237,6 +237,13 @@ ssize_t part_size_show(struct device *dev,
 	return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 	return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 }
 }
 
 
+ssize_t part_ro_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
+{
+	struct hd_struct *p = dev_to_part(dev);
+	return sprintf(buf, "%d\n", p->policy ? 1 : 0);
+}
+
 ssize_t part_alignment_offset_show(struct device *dev,
 ssize_t part_alignment_offset_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 				   struct device_attribute *attr, char *buf)
 {
 {
@@ -312,6 +319,7 @@ ssize_t part_fail_store(struct device *dev,
 static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
 static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
 static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
+static DEVICE_ATTR(ro, S_IRUGO, part_ro_show, NULL);
 static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL);
 static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL);
 static DEVICE_ATTR(discard_alignment, S_IRUGO, part_discard_alignment_show,
 static DEVICE_ATTR(discard_alignment, S_IRUGO, part_discard_alignment_show,
 		   NULL);
 		   NULL);
@@ -326,6 +334,7 @@ static struct attribute *part_attrs[] = {
 	&dev_attr_partition.attr,
 	&dev_attr_partition.attr,
 	&dev_attr_start.attr,
 	&dev_attr_start.attr,
 	&dev_attr_size.attr,
 	&dev_attr_size.attr,
+	&dev_attr_ro.attr,
 	&dev_attr_alignment_offset.attr,
 	&dev_attr_alignment_offset.attr,
 	&dev_attr_discard_alignment.attr,
 	&dev_attr_discard_alignment.attr,
 	&dev_attr_stat.attr,
 	&dev_attr_stat.attr,
@@ -549,7 +558,7 @@ void register_disk(struct gendisk *disk)
 		goto exit;
 		goto exit;
 
 
 	bdev->bd_invalidated = 1;
 	bdev->bd_invalidated = 1;
-	err = blkdev_get(bdev, FMODE_READ);
+	err = blkdev_get(bdev, FMODE_READ, NULL);
 	if (err < 0)
 	if (err < 0)
 		goto exit;
 		goto exit;
 	blkdev_put(bdev, FMODE_READ);
 	blkdev_put(bdev, FMODE_READ);

+ 7 - 14
fs/reiserfs/journal.c

@@ -2552,8 +2552,6 @@ static int release_journal_dev(struct super_block *super,
 	result = 0;
 	result = 0;
 
 
 	if (journal->j_dev_bd != NULL) {
 	if (journal->j_dev_bd != NULL) {
-		if (journal->j_dev_bd->bd_dev != super->s_dev)
-			bd_release(journal->j_dev_bd);
 		result = blkdev_put(journal->j_dev_bd, journal->j_dev_mode);
 		result = blkdev_put(journal->j_dev_bd, journal->j_dev_mode);
 		journal->j_dev_bd = NULL;
 		journal->j_dev_bd = NULL;
 	}
 	}
@@ -2571,7 +2569,7 @@ static int journal_init_dev(struct super_block *super,
 {
 {
 	int result;
 	int result;
 	dev_t jdev;
 	dev_t jdev;
-	fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE;
+	fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 	char b[BDEVNAME_SIZE];
 	char b[BDEVNAME_SIZE];
 
 
 	result = 0;
 	result = 0;
@@ -2585,7 +2583,10 @@ static int journal_init_dev(struct super_block *super,
 
 
 	/* there is no "jdev" option and journal is on separate device */
 	/* there is no "jdev" option and journal is on separate device */
 	if ((!jdev_name || !jdev_name[0])) {
 	if ((!jdev_name || !jdev_name[0])) {
-		journal->j_dev_bd = open_by_devnum(jdev, blkdev_mode);
+		if (jdev == super->s_dev)
+			blkdev_mode &= ~FMODE_EXCL;
+		journal->j_dev_bd = blkdev_get_by_dev(jdev, blkdev_mode,
+						      journal);
 		journal->j_dev_mode = blkdev_mode;
 		journal->j_dev_mode = blkdev_mode;
 		if (IS_ERR(journal->j_dev_bd)) {
 		if (IS_ERR(journal->j_dev_bd)) {
 			result = PTR_ERR(journal->j_dev_bd);
 			result = PTR_ERR(journal->j_dev_bd);
@@ -2594,22 +2595,14 @@ static int journal_init_dev(struct super_block *super,
 					 "cannot init journal device '%s': %i",
 					 "cannot init journal device '%s': %i",
 					 __bdevname(jdev, b), result);
 					 __bdevname(jdev, b), result);
 			return result;
 			return result;
-		} else if (jdev != super->s_dev) {
-			result = bd_claim(journal->j_dev_bd, journal);
-			if (result) {
-				blkdev_put(journal->j_dev_bd, blkdev_mode);
-				return result;
-			}
-
+		} else if (jdev != super->s_dev)
 			set_blocksize(journal->j_dev_bd, super->s_blocksize);
 			set_blocksize(journal->j_dev_bd, super->s_blocksize);
-		}
 
 
 		return 0;
 		return 0;
 	}
 	}
 
 
 	journal->j_dev_mode = blkdev_mode;
 	journal->j_dev_mode = blkdev_mode;
-	journal->j_dev_bd = open_bdev_exclusive(jdev_name,
-						blkdev_mode, journal);
+	journal->j_dev_bd = blkdev_get_by_path(jdev_name, blkdev_mode, journal);
 	if (IS_ERR(journal->j_dev_bd)) {
 	if (IS_ERR(journal->j_dev_bd)) {
 		result = PTR_ERR(journal->j_dev_bd);
 		result = PTR_ERR(journal->j_dev_bd);
 		journal->j_dev_bd = NULL;
 		journal->j_dev_bd = NULL;

+ 10 - 9
fs/super.c

@@ -766,13 +766,13 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 {
 {
 	struct block_device *bdev;
 	struct block_device *bdev;
 	struct super_block *s;
 	struct super_block *s;
-	fmode_t mode = FMODE_READ;
+	fmode_t mode = FMODE_READ | FMODE_EXCL;
 	int error = 0;
 	int error = 0;
 
 
 	if (!(flags & MS_RDONLY))
 	if (!(flags & MS_RDONLY))
 		mode |= FMODE_WRITE;
 		mode |= FMODE_WRITE;
 
 
-	bdev = open_bdev_exclusive(dev_name, mode, fs_type);
+	bdev = blkdev_get_by_path(dev_name, mode, fs_type);
 	if (IS_ERR(bdev))
 	if (IS_ERR(bdev))
 		return ERR_CAST(bdev);
 		return ERR_CAST(bdev);
 
 
@@ -801,13 +801,13 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 
 
 		/*
 		/*
 		 * s_umount nests inside bd_mutex during
 		 * s_umount nests inside bd_mutex during
-		 * __invalidate_device().  close_bdev_exclusive()
-		 * acquires bd_mutex and can't be called under
-		 * s_umount.  Drop s_umount temporarily.  This is safe
-		 * as we're holding an active reference.
+		 * __invalidate_device().  blkdev_put() acquires
+		 * bd_mutex and can't be called under s_umount.  Drop
+		 * s_umount temporarily.  This is safe as we're
+		 * holding an active reference.
 		 */
 		 */
 		up_write(&s->s_umount);
 		up_write(&s->s_umount);
-		close_bdev_exclusive(bdev, mode);
+		blkdev_put(bdev, mode);
 		down_write(&s->s_umount);
 		down_write(&s->s_umount);
 	} else {
 	} else {
 		char b[BDEVNAME_SIZE];
 		char b[BDEVNAME_SIZE];
@@ -831,7 +831,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 error_s:
 error_s:
 	error = PTR_ERR(s);
 	error = PTR_ERR(s);
 error_bdev:
 error_bdev:
-	close_bdev_exclusive(bdev, mode);
+	blkdev_put(bdev, mode);
 error:
 error:
 	return ERR_PTR(error);
 	return ERR_PTR(error);
 }
 }
@@ -862,7 +862,8 @@ void kill_block_super(struct super_block *sb)
 	bdev->bd_super = NULL;
 	bdev->bd_super = NULL;
 	generic_shutdown_super(sb);
 	generic_shutdown_super(sb);
 	sync_blockdev(bdev);
 	sync_blockdev(bdev);
-	close_bdev_exclusive(bdev, mode);
+	WARN_ON_ONCE(!(mode & FMODE_EXCL));
+	blkdev_put(bdev, mode | FMODE_EXCL);
 }
 }
 
 
 EXPORT_SYMBOL(kill_block_super);
 EXPORT_SYMBOL(kill_block_super);

+ 3 - 2
fs/xfs/linux-2.6/xfs_super.c

@@ -606,7 +606,8 @@ xfs_blkdev_get(
 {
 {
 	int			error = 0;
 	int			error = 0;
 
 
-	*bdevp = open_bdev_exclusive(name, FMODE_READ|FMODE_WRITE, mp);
+	*bdevp = blkdev_get_by_path(name, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+				    mp);
 	if (IS_ERR(*bdevp)) {
 	if (IS_ERR(*bdevp)) {
 		error = PTR_ERR(*bdevp);
 		error = PTR_ERR(*bdevp);
 		printk("XFS: Invalid device [%s], error=%d\n", name, error);
 		printk("XFS: Invalid device [%s], error=%d\n", name, error);
@@ -620,7 +621,7 @@ xfs_blkdev_put(
 	struct block_device	*bdev)
 	struct block_device	*bdev)
 {
 {
 	if (bdev)
 	if (bdev)
-		close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
+		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 }
 
 
 /*
 /*

+ 13 - 12
include/linux/fs.h

@@ -663,7 +663,7 @@ struct block_device {
 	void *			bd_holder;
 	void *			bd_holder;
 	int			bd_holders;
 	int			bd_holders;
 #ifdef CONFIG_SYSFS
 #ifdef CONFIG_SYSFS
-	struct list_head	bd_holder_list;
+	struct gendisk *	bd_holder_disk;	/* for sysfs slave linkng */
 #endif
 #endif
 	struct block_device *	bd_contains;
 	struct block_device *	bd_contains;
 	unsigned		bd_block_size;
 	unsigned		bd_block_size;
@@ -2006,7 +2006,6 @@ extern struct block_device *bdgrab(struct block_device *bdev);
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern void bdput(struct block_device *);
-extern struct block_device *open_by_devnum(dev_t, fmode_t);
 extern void invalidate_bdev(struct block_device *);
 extern void invalidate_bdev(struct block_device *);
 extern int sync_blockdev(struct block_device *bdev);
 extern int sync_blockdev(struct block_device *bdev);
 extern struct super_block *freeze_bdev(struct block_device *);
 extern struct super_block *freeze_bdev(struct block_device *);
@@ -2037,16 +2036,20 @@ extern const struct file_operations def_fifo_fops;
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
 extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
 extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
 extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
-extern int blkdev_get(struct block_device *, fmode_t);
-extern int blkdev_put(struct block_device *, fmode_t);
-extern int bd_claim(struct block_device *, void *);
-extern void bd_release(struct block_device *);
+extern int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder);
+extern struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
+					       void *holder);
+extern struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode,
+					      void *holder);
+extern int blkdev_put(struct block_device *bdev, fmode_t mode);
 #ifdef CONFIG_SYSFS
 #ifdef CONFIG_SYSFS
-extern int bd_claim_by_disk(struct block_device *, void *, struct gendisk *);
-extern void bd_release_from_disk(struct block_device *, struct gendisk *);
+extern int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk);
 #else
 #else
-#define bd_claim_by_disk(bdev, holder, disk)	bd_claim(bdev, holder)
-#define bd_release_from_disk(bdev, disk)	bd_release(bdev)
+static inline int bd_link_disk_holder(struct block_device *bdev,
+				      struct gendisk *disk)
+{
+	return 0;
+}
 #endif
 #endif
 #endif
 #endif
 
 
@@ -2082,8 +2085,6 @@ static inline void unregister_chrdev(unsigned int major, const char *name)
 extern const char *__bdevname(dev_t, char *buffer);
 extern const char *__bdevname(dev_t, char *buffer);
 extern const char *bdevname(struct block_device *bdev, char *buffer);
 extern const char *bdevname(struct block_device *bdev, char *buffer);
 extern struct block_device *lookup_bdev(const char *);
 extern struct block_device *lookup_bdev(const char *);
-extern struct block_device *open_bdev_exclusive(const char *, fmode_t, void *);
-extern void close_bdev_exclusive(struct block_device *, fmode_t);
 extern void blkdev_show(struct seq_file *,off_t);
 extern void blkdev_show(struct seq_file *,off_t);
 
 
 #else
 #else

+ 0 - 1
include/linux/fsl-diu-fb.h

@@ -54,7 +54,6 @@ struct aoi_display_offset {
 };
 };
 
 
 #define MFB_SET_CHROMA_KEY	_IOW('M', 1, struct mfb_chroma_key)
 #define MFB_SET_CHROMA_KEY	_IOW('M', 1, struct mfb_chroma_key)
-#define MFB_WAIT_FOR_VSYNC	_IOW('F', 0x20, u_int32_t)
 #define MFB_SET_BRIGHTNESS	_IOW('M', 3, __u8)
 #define MFB_SET_BRIGHTNESS	_IOW('M', 3, __u8)
 
 
 #define MFB_SET_ALPHA		0x80014d00
 #define MFB_SET_ALPHA		0x80014d00

+ 0 - 22
include/linux/i2c-id.h

@@ -32,28 +32,6 @@
  */
  */
 
 
 /* --- Bit algorithm adapters						*/
 /* --- Bit algorithm adapters						*/
-#define I2C_HW_B_BT848		0x010005 /* BT848 video boards */
-#define I2C_HW_B_RIVA		0x010010 /* Riva based graphics cards */
-#define I2C_HW_B_ZR36067	0x010019 /* Zoran-36057/36067 based boards */
 #define I2C_HW_B_CX2388x	0x01001b /* connexant 2388x based tv cards */
 #define I2C_HW_B_CX2388x	0x01001b /* connexant 2388x based tv cards */
-#define I2C_HW_B_EM28XX		0x01001f /* em28xx video capture cards */
-#define I2C_HW_B_CX2341X	0x010020 /* Conexant CX2341X MPEG encoder cards */
-#define I2C_HW_B_CX23885	0x010022 /* conexant 23885 based tv cards (bus1) */
-#define I2C_HW_B_AU0828		0x010023 /* auvitek au0828 usb bridge */
-#define I2C_HW_B_CX231XX	0x010024 /* Conexant CX231XX USB based cards */
-#define I2C_HW_B_HDPVR		0x010025 /* Hauppauge HD PVR */
-
-/* --- SGI adapters							*/
-#define I2C_HW_SGI_VINO		0x160000
-
-/* --- SMBus only adapters						*/
-#define I2C_HW_SMBUS_W9968CF	0x04000d
-#define I2C_HW_SMBUS_OV511	0x04000e /* OV511(+) USB 1.1 webcam ICs */
-#define I2C_HW_SMBUS_OV518	0x04000f /* OV518(+) USB 1.1 webcam ICs */
-#define I2C_HW_SMBUS_CAFE	0x040012 /* Marvell 88ALP01 "CAFE" cam  */
-
-/* --- Miscellaneous adapters */
-#define I2C_HW_SAA7146		0x060000 /* SAA7146 video decoder bus */
-#define I2C_HW_SAA7134		0x090000 /* SAA7134 video decoder bus */
 
 
 #endif /* LINUX_I2C_ID_H */
 #endif /* LINUX_I2C_ID_H */

+ 1 - 1
include/linux/i2c.h

@@ -353,7 +353,7 @@ struct i2c_algorithm {
  */
  */
 struct i2c_adapter {
 struct i2c_adapter {
 	struct module *owner;
 	struct module *owner;
-	unsigned int id;
+	unsigned int id __deprecated;
 	unsigned int class;		  /* classes to allow probing for */
 	unsigned int class;		  /* classes to allow probing for */
 	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 	void *algo_data;
 	void *algo_data;

+ 1 - 244
include/linux/kernel.h

@@ -17,13 +17,11 @@
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
 #include <linux/log2.h>
 #include <linux/typecheck.h>
 #include <linux/typecheck.h>
+#include <linux/printk.h>
 #include <linux/dynamic_debug.h>
 #include <linux/dynamic_debug.h>
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 #include <asm/bug.h>
 
 
-extern const char linux_banner[];
-extern const char linux_proc_banner[];
-
 #define USHRT_MAX	((u16)(~0U))
 #define USHRT_MAX	((u16)(~0U))
 #define SHRT_MAX	((s16)(USHRT_MAX>>1))
 #define SHRT_MAX	((s16)(USHRT_MAX>>1))
 #define SHRT_MIN	((s16)(-SHRT_MAX - 1))
 #define SHRT_MIN	((s16)(-SHRT_MAX - 1))
@@ -110,31 +108,6 @@ extern const char linux_proc_banner[];
  */
  */
 #define lower_32_bits(n) ((u32)(n))
 #define lower_32_bits(n) ((u32)(n))
 
 
-#define	KERN_EMERG	"<0>"	/* system is unusable			*/
-#define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
-#define	KERN_CRIT	"<2>"	/* critical conditions			*/
-#define	KERN_ERR	"<3>"	/* error conditions			*/
-#define	KERN_WARNING	"<4>"	/* warning conditions			*/
-#define	KERN_NOTICE	"<5>"	/* normal but significant condition	*/
-#define	KERN_INFO	"<6>"	/* informational			*/
-#define	KERN_DEBUG	"<7>"	/* debug-level messages			*/
-
-/* Use the default kernel loglevel */
-#define KERN_DEFAULT	"<d>"
-/*
- * Annotation for a "continued" line of log printout (only done after a
- * line that had no enclosing \n). Only to be used by core/arch code
- * during early bootup (a continued line is not SMP-safe otherwise).
- */
-#define	KERN_CONT	"<c>"
-
-extern int console_printk[];
-
-#define console_loglevel (console_printk[0])
-#define default_message_loglevel (console_printk[1])
-#define minimum_console_loglevel (console_printk[2])
-#define default_console_loglevel (console_printk[3])
-
 struct completion;
 struct completion;
 struct pt_regs;
 struct pt_regs;
 struct user;
 struct user;
@@ -187,11 +160,6 @@ static inline void might_fault(void)
 }
 }
 #endif
 #endif
 
 
-struct va_format {
-	const char *fmt;
-	va_list *va;
-};
-
 extern struct atomic_notifier_head panic_notifier_list;
 extern struct atomic_notifier_head panic_notifier_list;
 extern long (*panic_blink)(int state);
 extern long (*panic_blink)(int state);
 NORET_TYPE void panic(const char * fmt, ...)
 NORET_TYPE void panic(const char * fmt, ...)
@@ -245,115 +213,8 @@ extern int func_ptr_is_kernel_text(void *ptr);
 struct pid;
 struct pid;
 extern struct pid *session_of_pgrp(struct pid *pgrp);
 extern struct pid *session_of_pgrp(struct pid *pgrp);
 
 
-/*
- * FW_BUG
- * Add this to a message where you are sure the firmware is buggy or behaves
- * really stupid or out of spec. Be aware that the responsible BIOS developer
- * should be able to fix this issue or at least get a concrete idea of the
- * problem by reading your message without the need of looking at the kernel
- * code.
- * 
- * Use it for definite and high priority BIOS bugs.
- *
- * FW_WARN
- * Use it for not that clear (e.g. could the kernel messed up things already?)
- * and medium priority BIOS bugs.
- *
- * FW_INFO
- * Use this one if you want to tell the user or vendor about something
- * suspicious, but generally harmless related to the firmware.
- *
- * Use it for information or very low priority BIOS bugs.
- */
-#define FW_BUG		"[Firmware Bug]: "
-#define FW_WARN		"[Firmware Warn]: "
-#define FW_INFO		"[Firmware Info]: "
-
-/*
- * HW_ERR
- * Add this to a message for hardware errors, so that user can report
- * it to hardware vendor instead of LKML or software vendor.
- */
-#define HW_ERR		"[Hardware Error]: "
-
-#ifdef CONFIG_PRINTK
-asmlinkage int vprintk(const char *fmt, va_list args)
-	__attribute__ ((format (printf, 1, 0)));
-asmlinkage int printk(const char * fmt, ...)
-	__attribute__ ((format (printf, 1, 2))) __cold;
-
-/*
- * Please don't use printk_ratelimit(), because it shares ratelimiting state
- * with all other unrelated printk_ratelimit() callsites.  Instead use
- * printk_ratelimited() or plain old __ratelimit().
- */
-extern int __printk_ratelimit(const char *func);
-#define printk_ratelimit() __printk_ratelimit(__func__)
-extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
-				   unsigned int interval_msec);
-
-extern int printk_delay_msec;
-extern int dmesg_restrict;
-
-/*
- * Print a one-time message (analogous to WARN_ONCE() et al):
- */
-#define printk_once(x...) ({			\
-	static bool __print_once;		\
-						\
-	if (!__print_once) {			\
-		__print_once = true;		\
-		printk(x);			\
-	}					\
-})
-
-void log_buf_kexec_setup(void);
-#else
-static inline int vprintk(const char *s, va_list args)
-	__attribute__ ((format (printf, 1, 0)));
-static inline int vprintk(const char *s, va_list args) { return 0; }
-static inline int printk(const char *s, ...)
-	__attribute__ ((format (printf, 1, 2)));
-static inline int __cold printk(const char *s, ...) { return 0; }
-static inline int printk_ratelimit(void) { return 0; }
-static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
-					  unsigned int interval_msec)	\
-		{ return false; }
-
-/* No effect, but we still get type checking even in the !PRINTK case: */
-#define printk_once(x...) printk(x)
-
-static inline void log_buf_kexec_setup(void)
-{
-}
-#endif
-
-/*
- * Dummy printk for disabled debugging statements to use whilst maintaining
- * gcc's format and side-effect checking.
- */
-static inline __attribute__ ((format (printf, 1, 2)))
-int no_printk(const char *s, ...) { return 0; }
-
-extern int printk_needs_cpu(int cpu);
-extern void printk_tick(void);
-
-extern void asmlinkage __attribute__((format(printf, 1, 2)))
-	early_printk(const char *fmt, ...);
-
 unsigned long int_sqrt(unsigned long);
 unsigned long int_sqrt(unsigned long);
 
 
-static inline void console_silent(void)
-{
-	console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
-	if (console_loglevel)
-		console_loglevel = 15;
-}
-
 extern void bust_spinlocks(int yes);
 extern void bust_spinlocks(int yes);
 extern void wake_up_klogd(void);
 extern void wake_up_klogd(void);
 extern int oops_in_progress;		/* If set, an oops, panic(), BUG() or die() is in progress */
 extern int oops_in_progress;		/* If set, an oops, panic(), BUG() or die() is in progress */
@@ -390,22 +251,6 @@ extern enum system_states {
 #define TAINT_CRAP			10
 #define TAINT_CRAP			10
 #define TAINT_FIRMWARE_WORKAROUND	11
 #define TAINT_FIRMWARE_WORKAROUND	11
 
 
-extern void dump_stack(void) __cold;
-
-enum {
-	DUMP_PREFIX_NONE,
-	DUMP_PREFIX_ADDRESS,
-	DUMP_PREFIX_OFFSET
-};
-extern void hex_dump_to_buffer(const void *buf, size_t len,
-				int rowsize, int groupsize,
-				char *linebuf, size_t linebuflen, bool ascii);
-extern void print_hex_dump(const char *level, const char *prefix_str,
-				int prefix_type, int rowsize, int groupsize,
-				const void *buf, size_t len, bool ascii);
-extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
-			const void *buf, size_t len);
-
 extern const char hex_asc[];
 extern const char hex_asc[];
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
 #define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
 #define hex_asc_hi(x)	hex_asc[((x) & 0xf0) >> 4]
@@ -419,94 +264,6 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 
 
 extern int hex_to_bin(char ch);
 extern int hex_to_bin(char ch);
 
 
-#ifndef pr_fmt
-#define pr_fmt(fmt) fmt
-#endif
-
-#define pr_emerg(fmt, ...) \
-        printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_alert(fmt, ...) \
-        printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_crit(fmt, ...) \
-        printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_err(fmt, ...) \
-        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning(fmt, ...) \
-        printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn pr_warning
-#define pr_notice(fmt, ...) \
-        printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info(fmt, ...) \
-        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_cont(fmt, ...) \
-	printk(KERN_CONT fmt, ##__VA_ARGS__)
-
-/* pr_devel() should produce zero code unless DEBUG is defined */
-#ifdef DEBUG
-#define pr_devel(fmt, ...) \
-	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-#else
-#define pr_devel(fmt, ...) \
-	({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
-#endif
-
-/* If you are writing a driver, please use dev_dbg instead */
-#if defined(DEBUG)
-#define pr_debug(fmt, ...) \
-	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-#elif defined(CONFIG_DYNAMIC_DEBUG)
-/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
-#define pr_debug(fmt, ...) \
-	dynamic_pr_debug(fmt, ##__VA_ARGS__)
-#else
-#define pr_debug(fmt, ...) \
-	({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
-#endif
-
-/*
- * ratelimited messages with local ratelimit_state,
- * no local ratelimit_state used in the !PRINTK case
- */
-#ifdef CONFIG_PRINTK
-#define printk_ratelimited(fmt, ...)  ({				\
-	static DEFINE_RATELIMIT_STATE(_rs,				\
-				      DEFAULT_RATELIMIT_INTERVAL,	\
-				      DEFAULT_RATELIMIT_BURST);		\
-									\
-	if (__ratelimit(&_rs))						\
-		printk(fmt, ##__VA_ARGS__);				\
-})
-#else
-/* No effect, but we still get type checking even in the !PRINTK case: */
-#define printk_ratelimited printk
-#endif
-
-#define pr_emerg_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_alert_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_crit_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_err_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn_ratelimited pr_warning_ratelimited
-#define pr_notice_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
-/* no pr_cont_ratelimited, don't do that... */
-/* If you are writing a driver, please use dev_dbg instead */
-#if defined(DEBUG)
-#define pr_debug_ratelimited(fmt, ...) \
-	printk_ratelimited(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
-#else
-#define pr_debug_ratelimited(fmt, ...) \
-	({ if (0) printk_ratelimited(KERN_DEBUG pr_fmt(fmt), \
-				     ##__VA_ARGS__); 0; })
-#endif
-
 /*
 /*
  * General tracing related utility functions - trace_printk(),
  * General tracing related utility functions - trace_printk(),
  * tracing_on/tracing_off and tracing_start()/tracing_stop
  * tracing_on/tracing_off and tracing_start()/tracing_stop

+ 248 - 0
include/linux/printk.h

@@ -0,0 +1,248 @@
+#ifndef __KERNEL_PRINTK__
+#define __KERNEL_PRINTK__
+
+extern const char linux_banner[];
+extern const char linux_proc_banner[];
+
+#define	KERN_EMERG	"<0>"	/* system is unusable			*/
+#define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
+#define	KERN_CRIT	"<2>"	/* critical conditions			*/
+#define	KERN_ERR	"<3>"	/* error conditions			*/
+#define	KERN_WARNING	"<4>"	/* warning conditions			*/
+#define	KERN_NOTICE	"<5>"	/* normal but significant condition	*/
+#define	KERN_INFO	"<6>"	/* informational			*/
+#define	KERN_DEBUG	"<7>"	/* debug-level messages			*/
+
+/* Use the default kernel loglevel */
+#define KERN_DEFAULT	"<d>"
+/*
+ * Annotation for a "continued" line of log printout (only done after a
+ * line that had no enclosing \n). Only to be used by core/arch code
+ * during early bootup (a continued line is not SMP-safe otherwise).
+ */
+#define	KERN_CONT	"<c>"
+
+extern int console_printk[];
+
+#define console_loglevel (console_printk[0])
+#define default_message_loglevel (console_printk[1])
+#define minimum_console_loglevel (console_printk[2])
+#define default_console_loglevel (console_printk[3])
+
+struct va_format {
+	const char *fmt;
+	va_list *va;
+};
+
+/*
+ * FW_BUG
+ * Add this to a message where you are sure the firmware is buggy or behaves
+ * really stupid or out of spec. Be aware that the responsible BIOS developer
+ * should be able to fix this issue or at least get a concrete idea of the
+ * problem by reading your message without the need of looking at the kernel
+ * code.
+ *
+ * Use it for definite and high priority BIOS bugs.
+ *
+ * FW_WARN
+ * Use it for not that clear (e.g. could the kernel messed up things already?)
+ * and medium priority BIOS bugs.
+ *
+ * FW_INFO
+ * Use this one if you want to tell the user or vendor about something
+ * suspicious, but generally harmless related to the firmware.
+ *
+ * Use it for information or very low priority BIOS bugs.
+ */
+#define FW_BUG		"[Firmware Bug]: "
+#define FW_WARN		"[Firmware Warn]: "
+#define FW_INFO		"[Firmware Info]: "
+
+/*
+ * HW_ERR
+ * Add this to a message for hardware errors, so that user can report
+ * it to hardware vendor instead of LKML or software vendor.
+ */
+#define HW_ERR		"[Hardware Error]: "
+
+#ifdef CONFIG_PRINTK
+asmlinkage int vprintk(const char *fmt, va_list args)
+	__attribute__ ((format (printf, 1, 0)));
+asmlinkage int printk(const char * fmt, ...)
+	__attribute__ ((format (printf, 1, 2))) __cold;
+
+/*
+ * Please don't use printk_ratelimit(), because it shares ratelimiting state
+ * with all other unrelated printk_ratelimit() callsites.  Instead use
+ * printk_ratelimited() or plain old __ratelimit().
+ */
+extern int __printk_ratelimit(const char *func);
+#define printk_ratelimit() __printk_ratelimit(__func__)
+extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
+				   unsigned int interval_msec);
+
+extern int printk_delay_msec;
+extern int dmesg_restrict;
+
+/*
+ * Print a one-time message (analogous to WARN_ONCE() et al):
+ */
+#define printk_once(x...) ({			\
+	static bool __print_once;		\
+						\
+	if (!__print_once) {			\
+		__print_once = true;		\
+		printk(x);			\
+	}					\
+})
+
+void log_buf_kexec_setup(void);
+#else
+static inline int vprintk(const char *s, va_list args)
+	__attribute__ ((format (printf, 1, 0)));
+static inline int vprintk(const char *s, va_list args) { return 0; }
+static inline int printk(const char *s, ...)
+	__attribute__ ((format (printf, 1, 2)));
+static inline int __cold printk(const char *s, ...) { return 0; }
+static inline int printk_ratelimit(void) { return 0; }
+static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
+					  unsigned int interval_msec)	\
+		{ return false; }
+
+/* No effect, but we still get type checking even in the !PRINTK case: */
+#define printk_once(x...) printk(x)
+
+static inline void log_buf_kexec_setup(void)
+{
+}
+#endif
+
+/*
+ * Dummy printk for disabled debugging statements to use whilst maintaining
+ * gcc's format and side-effect checking.
+ */
+static inline __attribute__ ((format (printf, 1, 2)))
+int no_printk(const char *s, ...) { return 0; }
+
+extern int printk_needs_cpu(int cpu);
+extern void printk_tick(void);
+
+extern void asmlinkage __attribute__((format(printf, 1, 2)))
+	early_printk(const char *fmt, ...);
+
+static inline void console_silent(void)
+{
+	console_loglevel = 0;
+}
+
+static inline void console_verbose(void)
+{
+	if (console_loglevel)
+		console_loglevel = 15;
+}
+
+extern void dump_stack(void) __cold;
+
+enum {
+	DUMP_PREFIX_NONE,
+	DUMP_PREFIX_ADDRESS,
+	DUMP_PREFIX_OFFSET
+};
+extern void hex_dump_to_buffer(const void *buf, size_t len,
+				int rowsize, int groupsize,
+				char *linebuf, size_t linebuflen, bool ascii);
+extern void print_hex_dump(const char *level, const char *prefix_str,
+				int prefix_type, int rowsize, int groupsize,
+				const void *buf, size_t len, bool ascii);
+extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+			const void *buf, size_t len);
+
+#ifndef pr_fmt
+#define pr_fmt(fmt) fmt
+#endif
+
+#define pr_emerg(fmt, ...) \
+        printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert(fmt, ...) \
+        printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit(fmt, ...) \
+        printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...) \
+        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning(fmt, ...) \
+        printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn pr_warning
+#define pr_notice(fmt, ...) \
+        printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) \
+        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_cont(fmt, ...) \
+	printk(KERN_CONT fmt, ##__VA_ARGS__)
+
+/* pr_devel() should produce zero code unless DEBUG is defined */
+#ifdef DEBUG
+#define pr_devel(fmt, ...) \
+	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define pr_devel(fmt, ...) \
+	({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
+#endif
+
+/* If you are writing a driver, please use dev_dbg instead */
+#if defined(DEBUG)
+#define pr_debug(fmt, ...) \
+	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
+#define pr_debug(fmt, ...) \
+	dynamic_pr_debug(fmt, ##__VA_ARGS__)
+#else
+#define pr_debug(fmt, ...) \
+	({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
+#endif
+
+/*
+ * ratelimited messages with local ratelimit_state,
+ * no local ratelimit_state used in the !PRINTK case
+ */
+#ifdef CONFIG_PRINTK
+#define printk_ratelimited(fmt, ...)  ({				\
+	static DEFINE_RATELIMIT_STATE(_rs,				\
+				      DEFAULT_RATELIMIT_INTERVAL,	\
+				      DEFAULT_RATELIMIT_BURST);		\
+									\
+	if (__ratelimit(&_rs))						\
+		printk(fmt, ##__VA_ARGS__);				\
+})
+#else
+/* No effect, but we still get type checking even in the !PRINTK case: */
+#define printk_ratelimited printk
+#endif
+
+#define pr_emerg_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn_ratelimited pr_warning_ratelimited
+#define pr_notice_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+/* no pr_cont_ratelimited, don't do that... */
+/* If you are writing a driver, please use dev_dbg instead */
+#if defined(DEBUG)
+#define pr_debug_ratelimited(fmt, ...) \
+	printk_ratelimited(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#else
+#define pr_debug_ratelimited(fmt, ...) \
+	({ if (0) printk_ratelimited(KERN_DEBUG pr_fmt(fmt), \
+				     ##__VA_ARGS__); 0; })
+#endif
+
+#endif

+ 4 - 5
include/linux/security.h

@@ -77,7 +77,6 @@ extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 extern int cap_task_setscheduler(struct task_struct *p);
 extern int cap_task_setscheduler(struct task_struct *p);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
 extern int cap_task_setnice(struct task_struct *p, int nice);
-extern int cap_syslog(int type, bool from_file);
 extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
 extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
 
 
 struct msghdr;
 struct msghdr;
@@ -1388,7 +1387,7 @@ struct security_operations {
 	int (*sysctl) (struct ctl_table *table, int op);
 	int (*sysctl) (struct ctl_table *table, int op);
 	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
 	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
 	int (*quota_on) (struct dentry *dentry);
 	int (*quota_on) (struct dentry *dentry);
-	int (*syslog) (int type, bool from_file);
+	int (*syslog) (int type);
 	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 
 
@@ -1671,7 +1670,7 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap);
 int security_sysctl(struct ctl_table *table, int op);
 int security_sysctl(struct ctl_table *table, int op);
 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
 int security_quota_on(struct dentry *dentry);
 int security_quota_on(struct dentry *dentry);
-int security_syslog(int type, bool from_file);
+int security_syslog(int type);
 int security_settime(struct timespec *ts, struct timezone *tz);
 int security_settime(struct timespec *ts, struct timezone *tz);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
@@ -1901,9 +1900,9 @@ static inline int security_quota_on(struct dentry *dentry)
 	return 0;
 	return 0;
 }
 }
 
 
-static inline int security_syslog(int type, bool from_file)
+static inline int security_syslog(int type)
 {
 {
-	return cap_syslog(type, from_file);
+	return 0;
 }
 }
 
 
 static inline int security_settime(struct timespec *ts, struct timezone *tz)
 static inline int security_settime(struct timespec *ts, struct timezone *tz)

+ 1 - 1
include/linux/sh_intc.h

@@ -79,7 +79,7 @@ struct intc_hw_desc {
 	unsigned int nr_subgroups;
 	unsigned int nr_subgroups;
 };
 };
 
 
-#define _INTC_ARRAY(a) a, a == NULL ? 0 : sizeof(a)/sizeof(*a)
+#define _INTC_ARRAY(a) a, __same_type(a, NULL) ? 0 : sizeof(a)/sizeof(*a)
 
 
 #define INTC_HW_DESC(vectors, groups, mask_regs,	\
 #define INTC_HW_DESC(vectors, groups, mask_regs,	\
 		     prio_regs,	sense_regs, ack_regs)	\
 		     prio_regs,	sense_regs, ack_regs)	\

+ 3 - 3
include/trace/events/block.h

@@ -486,16 +486,16 @@ TRACE_EVENT(block_split,
 );
 );
 
 
 /**
 /**
- * block_remap - map request for a partition to the raw device
+ * block_bio_remap - map request for a logical device to the raw device
  * @q: queue holding the operation
  * @q: queue holding the operation
  * @bio: revised operation
  * @bio: revised operation
  * @dev: device for the operation
  * @dev: device for the operation
  * @from: original sector for the operation
  * @from: original sector for the operation
  *
  *
- * An operation for a partition on a block device has been mapped to the
+ * An operation for a logical device has been mapped to the
  * raw block device.
  * raw block device.
  */
  */
-TRACE_EVENT(block_remap,
+TRACE_EVENT(block_bio_remap,
 
 
 	TP_PROTO(struct request_queue *q, struct bio *bio, dev_t dev,
 	TP_PROTO(struct request_queue *q, struct bio *bio, dev_t dev,
 		 sector_t from),
 		 sector_t from),

+ 3 - 2
kernel/power/swap.c

@@ -223,7 +223,7 @@ static int swsusp_swap_check(void)
 		return res;
 		return res;
 
 
 	root_swap = res;
 	root_swap = res;
-	res = blkdev_get(hib_resume_bdev, FMODE_WRITE);
+	res = blkdev_get(hib_resume_bdev, FMODE_WRITE, NULL);
 	if (res)
 	if (res)
 		return res;
 		return res;
 
 
@@ -907,7 +907,8 @@ int swsusp_check(void)
 {
 {
 	int error;
 	int error;
 
 
-	hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
+	hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device,
+					    FMODE_READ, NULL);
 	if (!IS_ERR(hib_resume_bdev)) {
 	if (!IS_ERR(hib_resume_bdev)) {
 		set_blocksize(hib_resume_bdev, PAGE_SIZE);
 		set_blocksize(hib_resume_bdev, PAGE_SIZE);
 		clear_page(swsusp_header);
 		clear_page(swsusp_header);

+ 14 - 1
kernel/printk.c

@@ -274,7 +274,20 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 	char c;
 	char c;
 	int error = 0;
 	int error = 0;
 
 
-	error = security_syslog(type, from_file);
+	/*
+	 * If this is from /proc/kmsg we only do the capabilities checks
+	 * at open time.
+	 */
+	if (type == SYSLOG_ACTION_OPEN || !from_file) {
+		if (dmesg_restrict && !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if ((type != SYSLOG_ACTION_READ_ALL &&
+		     type != SYSLOG_ACTION_SIZE_BUFFER) &&
+		    !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+	}
+
+	error = security_syslog(type);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 

+ 6 - 6
kernel/trace/blktrace.c

@@ -887,7 +887,7 @@ static void blk_add_trace_split(void *ignore,
 }
 }
 
 
 /**
 /**
- * blk_add_trace_remap - Add a trace for a remap operation
+ * blk_add_trace_bio_remap - Add a trace for a bio-remap operation
  * @ignore:	trace callback data parameter (not used)
  * @ignore:	trace callback data parameter (not used)
  * @q:		queue the io is for
  * @q:		queue the io is for
  * @bio:	the source bio
  * @bio:	the source bio
@@ -899,9 +899,9 @@ static void blk_add_trace_split(void *ignore,
  *     it spans a stripe (or similar). Add a trace for that action.
  *     it spans a stripe (or similar). Add a trace for that action.
  *
  *
  **/
  **/
-static void blk_add_trace_remap(void *ignore,
-				struct request_queue *q, struct bio *bio,
-				dev_t dev, sector_t from)
+static void blk_add_trace_bio_remap(void *ignore,
+				    struct request_queue *q, struct bio *bio,
+				    dev_t dev, sector_t from)
 {
 {
 	struct blk_trace *bt = q->blk_trace;
 	struct blk_trace *bt = q->blk_trace;
 	struct blk_io_trace_remap r;
 	struct blk_io_trace_remap r;
@@ -1016,7 +1016,7 @@ static void blk_register_tracepoints(void)
 	WARN_ON(ret);
 	WARN_ON(ret);
 	ret = register_trace_block_split(blk_add_trace_split, NULL);
 	ret = register_trace_block_split(blk_add_trace_split, NULL);
 	WARN_ON(ret);
 	WARN_ON(ret);
-	ret = register_trace_block_remap(blk_add_trace_remap, NULL);
+	ret = register_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
 	WARN_ON(ret);
 	WARN_ON(ret);
 	ret = register_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
 	ret = register_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
 	WARN_ON(ret);
 	WARN_ON(ret);
@@ -1025,7 +1025,7 @@ static void blk_register_tracepoints(void)
 static void blk_unregister_tracepoints(void)
 static void blk_unregister_tracepoints(void)
 {
 {
 	unregister_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
 	unregister_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
-	unregister_trace_block_remap(blk_add_trace_remap, NULL);
+	unregister_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
 	unregister_trace_block_split(blk_add_trace_split, NULL);
 	unregister_trace_block_split(blk_add_trace_split, NULL);
 	unregister_trace_block_unplug_io(blk_add_trace_unplug_io, NULL);
 	unregister_trace_block_unplug_io(blk_add_trace_unplug_io, NULL);
 	unregister_trace_block_unplug_timer(blk_add_trace_unplug_timer, NULL);
 	unregister_trace_block_unplug_timer(blk_add_trace_unplug_timer, NULL);

+ 2 - 1
mm/slub.c

@@ -3273,9 +3273,9 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
 		kfree(n);
 		kfree(n);
 		kfree(s);
 		kfree(s);
 	}
 	}
+err:
 	up_write(&slub_lock);
 	up_write(&slub_lock);
 
 
-err:
 	if (flags & SLAB_PANIC)
 	if (flags & SLAB_PANIC)
 		panic("Cannot create slabcache %s\n", name);
 		panic("Cannot create slabcache %s\n", name);
 	else
 	else
@@ -3862,6 +3862,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 			x += sprintf(buf + x, " N%d=%lu",
 			x += sprintf(buf + x, " N%d=%lu",
 					node, nodes[node]);
 					node, nodes[node]);
 #endif
 #endif
+	up_read(&slub_lock);
 	kfree(nodes);
 	kfree(nodes);
 	return x + sprintf(buf + x, "\n");
 	return x + sprintf(buf + x, "\n");
 }
 }

+ 4 - 3
mm/swapfile.c

@@ -1677,7 +1677,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	if (S_ISBLK(inode->i_mode)) {
 	if (S_ISBLK(inode->i_mode)) {
 		struct block_device *bdev = I_BDEV(inode);
 		struct block_device *bdev = I_BDEV(inode);
 		set_blocksize(bdev, p->old_block_size);
 		set_blocksize(bdev, p->old_block_size);
-		bd_release(bdev);
+		blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 	} else {
 	} else {
 		mutex_lock(&inode->i_mutex);
 		mutex_lock(&inode->i_mutex);
 		inode->i_flags &= ~S_SWAPFILE;
 		inode->i_flags &= ~S_SWAPFILE;
@@ -1939,7 +1939,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	error = -EINVAL;
 	error = -EINVAL;
 	if (S_ISBLK(inode->i_mode)) {
 	if (S_ISBLK(inode->i_mode)) {
 		bdev = I_BDEV(inode);
 		bdev = I_BDEV(inode);
-		error = bd_claim(bdev, sys_swapon);
+		error = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+				   sys_swapon);
 		if (error < 0) {
 		if (error < 0) {
 			bdev = NULL;
 			bdev = NULL;
 			error = -EINVAL;
 			error = -EINVAL;
@@ -2136,7 +2137,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 bad_swap:
 bad_swap:
 	if (bdev) {
 	if (bdev) {
 		set_blocksize(bdev, p->old_block_size);
 		set_blocksize(bdev, p->old_block_size);
-		bd_release(bdev);
+		blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 	}
 	}
 	destroy_swap_extents(p);
 	destroy_swap_extents(p);
 	swap_cgroup_swapoff(type);
 	swap_cgroup_swapoff(type);

+ 5 - 0
security/capability.c

@@ -17,6 +17,11 @@ static int cap_sysctl(ctl_table *table, int op)
 	return 0;
 	return 0;
 }
 }
 
 
+static int cap_syslog(int type)
+{
+	return 0;
+}
+
 static int cap_quotactl(int cmds, int type, int id, struct super_block *sb)
 static int cap_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
 {
 	return 0;
 	return 0;

+ 0 - 21
security/commoncap.c

@@ -27,7 +27,6 @@
 #include <linux/sched.h>
 #include <linux/sched.h>
 #include <linux/prctl.h>
 #include <linux/prctl.h>
 #include <linux/securebits.h>
 #include <linux/securebits.h>
-#include <linux/syslog.h>
 
 
 /*
 /*
  * If a non-root user executes a setuid-root binary in
  * If a non-root user executes a setuid-root binary in
@@ -883,26 +882,6 @@ error:
 	return error;
 	return error;
 }
 }
 
 
-/**
- * cap_syslog - Determine whether syslog function is permitted
- * @type: Function requested
- * @from_file: Whether this request came from an open file (i.e. /proc)
- *
- * Determine whether the current process is permitted to use a particular
- * syslog function, returning 0 if permission is granted, -ve if not.
- */
-int cap_syslog(int type, bool from_file)
-{
-	if (type != SYSLOG_ACTION_OPEN && from_file)
-		return 0;
-	if (dmesg_restrict && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if ((type != SYSLOG_ACTION_READ_ALL &&
-	     type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	return 0;
-}
-
 /**
 /**
  * cap_vm_enough_memory - Determine whether a new virtual mapping is permitted
  * cap_vm_enough_memory - Determine whether a new virtual mapping is permitted
  * @mm: The VM space in which the new mapping is to be made
  * @mm: The VM space in which the new mapping is to be made

+ 2 - 2
security/security.c

@@ -197,9 +197,9 @@ int security_quota_on(struct dentry *dentry)
 	return security_ops->quota_on(dentry);
 	return security_ops->quota_on(dentry);
 }
 }
 
 
-int security_syslog(int type, bool from_file)
+int security_syslog(int type)
 {
 {
-	return security_ops->syslog(type, from_file);
+	return security_ops->syslog(type);
 }
 }
 
 
 int security_settime(struct timespec *ts, struct timezone *tz)
 int security_settime(struct timespec *ts, struct timezone *tz)

+ 1 - 5
security/selinux/hooks.c

@@ -1973,14 +1973,10 @@ static int selinux_quota_on(struct dentry *dentry)
 	return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 	return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 }
 }
 
 
-static int selinux_syslog(int type, bool from_file)
+static int selinux_syslog(int type)
 {
 {
 	int rc;
 	int rc;
 
 
-	rc = cap_syslog(type, from_file);
-	if (rc)
-		return rc;
-
 	switch (type) {
 	switch (type) {
 	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
 	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
 	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
 	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */

+ 2 - 6
security/smack/smack_lsm.c

@@ -157,15 +157,11 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
  *
  *
  * Returns 0 on success, error code otherwise.
  * Returns 0 on success, error code otherwise.
  */
  */
-static int smack_syslog(int type, bool from_file)
+static int smack_syslog(int typefrom_file)
 {
 {
-	int rc;
+	int rc = 0;
 	char *sp = current_security();
 	char *sp = current_security();
 
 
-	rc = cap_syslog(type, from_file);
-	if (rc != 0)
-		return rc;
-
 	if (capable(CAP_MAC_OVERRIDE))
 	if (capable(CAP_MAC_OVERRIDE))
 		return 0;
 		return 0;