linux/drivers/block
Takashi Iwai 529e71e164 zram: fix unbalanced idr management at hot removal
The zram hot removal code calls idr_remove() even when zram_remove()
returns an error (typically -EBUSY).  This results in a leftover at the
device release, eventually leading to a crash when the module is
reloaded.

As described in the bug report below, the following procedure would
cause an Oops with zram:

 - provision three zram devices via modprobe zram num_devices=3
 - configure a size for each device
   + echo "1G" > /sys/block/$zram_name/disksize
 - mkfs and mount zram0 only
 - attempt to hot remove all three devices
   + echo 2 > /sys/class/zram-control/hot_remove
   + echo 1 > /sys/class/zram-control/hot_remove
   + echo 0 > /sys/class/zram-control/hot_remove
     - zram0 removal fails with EBUSY, as expected
 - unmount zram0
 - try zram0 hot remove again
   + echo 0 > /sys/class/zram-control/hot_remove
     - fails with ENODEV (unexpected)
 - unload zram kernel module
   + completes successfully
 - zram0 device node still exists
 - attempt to mount /dev/zram0
   + mount command is killed
   + following BUG is encountered

 BUG: unable to handle kernel paging request at ffffffffa0002ba0
 IP: get_disk+0x16/0x50
 Oops: 0000 [#1] SMP
 CPU: 0 PID: 252 Comm: mount Not tainted 4.9.0-rc6 #176
 Call Trace:
   exact_lock+0xc/0x20
   kobj_lookup+0xdc/0x160
   get_gendisk+0x2f/0x110
   __blkdev_get+0x10c/0x3c0
   blkdev_get+0x19d/0x2e0
   blkdev_open+0x56/0x70
   do_dentry_open.isra.19+0x1ff/0x310
   vfs_open+0x43/0x60
   path_openat+0x2c9/0xf30
   do_filp_open+0x79/0xd0
   do_sys_open+0x114/0x1e0
   SyS_open+0x19/0x20
   entry_SYSCALL_64_fastpath+0x13/0x94

This patch adds the proper error check in hot_remove_store() not to call
idr_remove() unconditionally.

Fixes: 17ec4cd985 ("zram: don't call idr_remove() from zram_remove()")
Bugzilla: https://bugzilla.opensuse.org/show_bug.cgi?id=1010970
Link: http://lkml.kernel.org/r/20161121132140.12683-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: David Disseldorp <ddiss@suse.de>
Reported-by: David Disseldorp <ddiss@suse.de>
Tested-by: David Disseldorp <ddiss@suse.de>
Acked-by: Minchan Kim <minchan@kernel.org>
Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: <stable@vger.kernel.org>    [4.4+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2016-11-30 16:32:52 -08:00
..
aoe aoe: fix crash in page count manipulation 2016-11-12 08:27:07 -07:00
drbd drbd: Fix kernel_sendmsg() usage - potential NULL deref 2016-11-09 17:08:32 -07:00
mtip32xx blk-mq: remove ->map_queue 2016-09-15 08:42:03 -06:00
paride paride: make 'verbose' parameter an 'int' again 2016-03-15 16:55:16 -07:00
rsxx block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
xen-blkback xen: features and fixes for 4.8-rc0 2016-07-27 11:35:37 -07:00
zram zram: fix unbalanced idr management at hot removal 2016-11-30 16:32:52 -08:00
amiflop.c block: drop owner assignment from platform_drivers 2014-10-20 16:20:18 +02:00
ataflop.c Merge branch 'for-3.16/core' of git://git.kernel.dk/linux-block into next 2014-06-02 09:29:34 -07:00
brd.c block/mm: make bdev_ops->rw_page() take a bool for read/write 2016-08-07 14:41:02 -06:00
cciss_cmd.h
cciss_scsi.c scsi: Do not set cmd_per_lun to 1 in the host template 2015-05-31 18:06:28 -07:00
cciss_scsi.h
cciss.c block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
cciss.h
cryptoloop.c block: cryptoloop - Use new skcipher interface 2016-01-27 20:35:43 +08:00
DAC960.c block: DAC960: print a hex number after a 0x prefix 2016-10-27 18:43:43 -07:00
DAC960.h
floppy.c Revert "floppy: refactor open() flags handling" 2016-08-25 08:56:51 -06:00
hd.c block: hd: remove deprecated IRQF_DISABLED 2014-10-01 08:16:07 -06:00
Kconfig cpqarray: remove it from the kernel 2016-03-14 09:06:01 -06:00
loop.c kthread: kthread worker API cleanup 2016-10-11 15:06:33 -07:00
loop.h block: loop: support DIO & AIO 2015-09-23 11:01:16 -06:00
Makefile drivers:block: cpqarray clean up 2016-03-15 15:59:47 -07:00
mg_disk.c mg_disk: fix error path in mg_probe() 2016-06-28 11:01:27 -06:00
nbd.c nbd: Fix error handling 2016-11-06 14:14:59 -07:00
null_blk.c Merge branch 'for-4.9/block-irq' of git://git.kernel.dk/linux-block 2016-10-09 17:29:33 -07:00
osdblk.c block, drivers: add REQ_OP_FLUSH operation 2016-06-07 13:41:38 -06:00
pktcdvd.c block: rename bio bi_rw to bi_opf 2016-08-07 14:41:02 -06:00
ps3disk.c block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
ps3vram.c block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
rbd_types.h rbd: support for exclusive-lock feature 2016-08-24 23:49:16 +02:00
rbd.c rbd: don't retry watch reregistration if header object is gone 2016-10-15 23:22:09 +02:00
skd_main.c block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
skd_s1120.h skd: fix formatting in skd_s1120.h 2013-11-08 09:10:30 -07:00
smart1,2.h
sunvdc.c block: convert to device_add_disk() 2016-06-27 12:26:08 -07:00
swim3.c powerpc: Move Power Macintosh drivers to generic byteswappers 2015-03-23 14:29:40 +11:00
swim_asm.S
swim.c block: drop owner assignment from platform_drivers 2014-10-20 16:20:18 +02:00
sx8.c sx8: use real time for the command seconds 2015-12-23 08:42:59 -07:00
umem.c block: rename bio bi_rw to bi_opf 2016-08-07 14:41:02 -06:00
umem.h
virtio_blk.c virtio_blk: Delete an unnecessary initialisation in init_vq() 2016-10-31 00:21:47 +02:00
xen-blkfront.c blk-mq: remove ->map_queue 2016-09-15 08:42:03 -06:00
xsysace.c block: systemace: Remove .owner field for driver 2014-08-21 20:37:54 -05:00
z2ram.c block: remove struct request buffer member 2014-04-15 14:03:02 -06:00