blk-cgroup: be able to remove the record of unplugged device

The bug is we're not able to remove the device from blkio cgroup's
per-device control files if it gets unplugged.

To reproduce the bug:

# mount -t cgroup -o blkio xxx /cgroup
# cd /cgroup
# echo "8:0 1000" > blkio.throttle.read_bps_device
# unplug the device
# cat blkio.throttle.read_bps_device
8:0 1000
# echo "8:0 0" > blkio.throttle.read_bps_device
-bash: echo: write error: No such device

After patching, the device removal will succeed.

Thanks for the comments of Paul, Zefan, and Vivek.

Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Paul Menage <paul@paulmenage.org>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by Wanlong Gao and committed by Jens Axboe d11bb446 8ad6a56f

Changed files
+16 -21
block
+16 -21
block/blk-cgroup.c
··· 785 785 { 786 786 char *s[4], *p, *major_s = NULL, *minor_s = NULL; 787 787 int ret; 788 - unsigned long major, minor, temp; 788 + unsigned long major, minor; 789 789 int i = 0; 790 790 dev_t dev; 791 - u64 bps, iops; 791 + u64 temp; 792 792 793 793 memset(s, 0, sizeof(s)); 794 794 ··· 826 826 827 827 dev = MKDEV(major, minor); 828 828 829 - ret = blkio_check_dev_num(dev); 829 + ret = strict_strtoull(s[1], 10, &temp); 830 830 if (ret) 831 - return ret; 831 + return -EINVAL; 832 + 833 + /* For rule removal, do not check for device presence. */ 834 + if (temp) { 835 + ret = blkio_check_dev_num(dev); 836 + if (ret) 837 + return ret; 838 + } 832 839 833 840 newpn->dev = dev; 834 841 835 - if (s[1] == NULL) 836 - return -EINVAL; 837 - 838 842 switch (plid) { 839 843 case BLKIO_POLICY_PROP: 840 - ret = strict_strtoul(s[1], 10, &temp); 841 - if (ret || (temp < BLKIO_WEIGHT_MIN && temp > 0) || 842 - temp > BLKIO_WEIGHT_MAX) 844 + if ((temp < BLKIO_WEIGHT_MIN && temp > 0) || 845 + temp > BLKIO_WEIGHT_MAX) 843 846 return -EINVAL; 844 847 845 848 newpn->plid = plid; ··· 853 850 switch(fileid) { 854 851 case BLKIO_THROTL_read_bps_device: 855 852 case BLKIO_THROTL_write_bps_device: 856 - ret = strict_strtoull(s[1], 10, &bps); 857 - if (ret) 858 - return -EINVAL; 859 - 860 853 newpn->plid = plid; 861 854 newpn->fileid = fileid; 862 - newpn->val.bps = bps; 855 + newpn->val.bps = temp; 863 856 break; 864 857 case BLKIO_THROTL_read_iops_device: 865 858 case BLKIO_THROTL_write_iops_device: 866 - ret = strict_strtoull(s[1], 10, &iops); 867 - if (ret) 868 - return -EINVAL; 869 - 870 - if (iops > THROTL_IOPS_MAX) 859 + if (temp > THROTL_IOPS_MAX) 871 860 return -EINVAL; 872 861 873 862 newpn->plid = plid; 874 863 newpn->fileid = fileid; 875 - newpn->val.iops = (unsigned int)iops; 864 + newpn->val.iops = (unsigned int)temp; 876 865 break; 877 866 } 878 867 break;