Commit ba6b17d68c8e3aa8d55d0474299cb931965c5ea5
Committed by
Linus Torvalds
1 parent
1fec117281
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
zram: fix umount-reset_store-mount race condition
Ganesh Mahendran was the first one who proposed to use bdev->bd_mutex to avoid ->bd_holders race condition: CPU0 CPU1 umount /* zram->init_done is true */ reset_store() bdev->bd_holders == 0 mount ... zram_make_request() zram_reset_device() However, his solution required some considerable amount of code movement, which we can avoid. Apart from using bdev->bd_mutex in reset_store(), this patch also simplifies zram_reset_device(). zram_reset_device() has a bool parameter reset_capacity which tells it whether disk capacity and itself disk should be reset. There are two zram_reset_device() callers: -- zram_exit() passes reset_capacity=false -- reset_store() passes reset_capacity=true So we can move reset_capacity-sensitive work out of zram_reset_device() and perform it unconditionally in reset_store(). This also lets us drop reset_capacity parameter from zram_reset_device() and pass zram pointer only. Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Reported-by: Ganesh Mahendran <opensource.ganesh@gmail.com> Cc: Minchan Kim <minchan@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 9 additions and 14 deletions Side-by-side Diff
drivers/block/zram/zram_drv.c
... | ... | @@ -715,7 +715,7 @@ |
715 | 715 | } |
716 | 716 | } |
717 | 717 | |
718 | -static void zram_reset_device(struct zram *zram, bool reset_capacity) | |
718 | +static void zram_reset_device(struct zram *zram) | |
719 | 719 | { |
720 | 720 | down_write(&zram->init_lock); |
721 | 721 | |
722 | 722 | |
... | ... | @@ -734,18 +734,7 @@ |
734 | 734 | memset(&zram->stats, 0, sizeof(zram->stats)); |
735 | 735 | |
736 | 736 | zram->disksize = 0; |
737 | - if (reset_capacity) | |
738 | - set_capacity(zram->disk, 0); | |
739 | - | |
740 | 737 | up_write(&zram->init_lock); |
741 | - | |
742 | - /* | |
743 | - * Revalidate disk out of the init_lock to avoid lockdep splat. | |
744 | - * It's okay because disk's capacity is protected by init_lock | |
745 | - * so that revalidate_disk always sees up-to-date capacity. | |
746 | - */ | |
747 | - if (reset_capacity) | |
748 | - revalidate_disk(zram->disk); | |
749 | 738 | } |
750 | 739 | |
751 | 740 | static ssize_t disksize_store(struct device *dev, |
... | ... | @@ -818,6 +807,7 @@ |
818 | 807 | if (!bdev) |
819 | 808 | return -ENOMEM; |
820 | 809 | |
810 | + mutex_lock(&bdev->bd_mutex); | |
821 | 811 | /* Do not reset an active device! */ |
822 | 812 | if (bdev->bd_holders) { |
823 | 813 | ret = -EBUSY; |
824 | 814 | |
825 | 815 | |
... | ... | @@ -835,12 +825,17 @@ |
835 | 825 | |
836 | 826 | /* Make sure all pending I/O is finished */ |
837 | 827 | fsync_bdev(bdev); |
828 | + zram_reset_device(zram); | |
829 | + set_capacity(zram->disk, 0); | |
830 | + | |
831 | + mutex_unlock(&bdev->bd_mutex); | |
832 | + revalidate_disk(zram->disk); | |
838 | 833 | bdput(bdev); |
839 | 834 | |
840 | - zram_reset_device(zram, true); | |
841 | 835 | return len; |
842 | 836 | |
843 | 837 | out: |
838 | + mutex_unlock(&bdev->bd_mutex); | |
844 | 839 | bdput(bdev); |
845 | 840 | return ret; |
846 | 841 | } |
... | ... | @@ -1186,7 +1181,7 @@ |
1186 | 1181 | * Shouldn't access zram->disk after destroy_device |
1187 | 1182 | * because destroy_device already released zram->disk. |
1188 | 1183 | */ |
1189 | - zram_reset_device(zram, false); | |
1184 | + zram_reset_device(zram); | |
1190 | 1185 | } |
1191 | 1186 | |
1192 | 1187 | unregister_blkdev(zram_major, "zram"); |