diff options
Diffstat (limited to 'drivers/block/loop.c')
| -rw-r--r-- | drivers/block/loop.c | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c77983ea86c..3d806820280 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -76,6 +76,8 @@ | |||
| 76 | #include <linux/splice.h> | 76 | #include <linux/splice.h> |
| 77 | #include <linux/sysfs.h> | 77 | #include <linux/sysfs.h> |
| 78 | #include <linux/miscdevice.h> | 78 | #include <linux/miscdevice.h> |
| 79 | #include <linux/falloc.h> | ||
| 80 | |||
| 79 | #include <asm/uaccess.h> | 81 | #include <asm/uaccess.h> |
| 80 | 82 | ||
| 81 | static DEFINE_IDR(loop_index_idr); | 83 | static DEFINE_IDR(loop_index_idr); |
| @@ -407,6 +409,29 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) | |||
| 407 | } | 409 | } |
| 408 | } | 410 | } |
| 409 | 411 | ||
| 412 | /* | ||
| 413 | * We use punch hole to reclaim the free space used by the | ||
| 414 | * image a.k.a. discard. However we do support discard if | ||
| 415 | * encryption is enabled, because it may give an attacker | ||
| 416 | * useful information. | ||
| 417 | */ | ||
| 418 | if (bio->bi_rw & REQ_DISCARD) { | ||
| 419 | struct file *file = lo->lo_backing_file; | ||
| 420 | int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; | ||
| 421 | |||
| 422 | if ((!file->f_op->fallocate) || | ||
| 423 | lo->lo_encrypt_key_size) { | ||
| 424 | ret = -EOPNOTSUPP; | ||
| 425 | goto out; | ||
| 426 | } | ||
| 427 | ret = file->f_op->fallocate(file, mode, pos, | ||
| 428 | bio->bi_size); | ||
| 429 | if (unlikely(ret && ret != -EINVAL && | ||
| 430 | ret != -EOPNOTSUPP)) | ||
| 431 | ret = -EIO; | ||
| 432 | goto out; | ||
| 433 | } | ||
| 434 | |||
| 410 | ret = lo_send(lo, bio, pos); | 435 | ret = lo_send(lo, bio, pos); |
| 411 | 436 | ||
| 412 | if ((bio->bi_rw & REQ_FUA) && !ret) { | 437 | if ((bio->bi_rw & REQ_FUA) && !ret) { |
| @@ -622,7 +647,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, | |||
| 622 | goto out_putf; | 647 | goto out_putf; |
| 623 | 648 | ||
| 624 | fput(old_file); | 649 | fput(old_file); |
| 625 | if (max_part > 0) | 650 | if (lo->lo_flags & LO_FLAGS_PARTSCAN) |
| 626 | ioctl_by_bdev(bdev, BLKRRPART, 0); | 651 | ioctl_by_bdev(bdev, BLKRRPART, 0); |
| 627 | return 0; | 652 | return 0; |
| 628 | 653 | ||
| @@ -699,16 +724,25 @@ static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf) | |||
| 699 | return sprintf(buf, "%s\n", autoclear ? "1" : "0"); | 724 | return sprintf(buf, "%s\n", autoclear ? "1" : "0"); |
| 700 | } | 725 | } |
| 701 | 726 | ||
| 727 | static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf) | ||
| 728 | { | ||
| 729 | int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN); | ||
| 730 | |||
| 731 | return sprintf(buf, "%s\n", partscan ? "1" : "0"); | ||
| 732 | } | ||
| 733 | |||
| 702 | LOOP_ATTR_RO(backing_file); | 734 | LOOP_ATTR_RO(backing_file); |
| 703 | LOOP_ATTR_RO(offset); | 735 | LOOP_ATTR_RO(offset); |
| 704 | LOOP_ATTR_RO(sizelimit); | 736 | LOOP_ATTR_RO(sizelimit); |
| 705 | LOOP_ATTR_RO(autoclear); | 737 | LOOP_ATTR_RO(autoclear); |
| 738 | LOOP_ATTR_RO(partscan); | ||
| 706 | 739 | ||
| 707 | static struct attribute *loop_attrs[] = { | 740 | static struct attribute *loop_attrs[] = { |
| 708 | &loop_attr_backing_file.attr, | 741 | &loop_attr_backing_file.attr, |
| 709 | &loop_attr_offset.attr, | 742 | &loop_attr_offset.attr, |
| 710 | &loop_attr_sizelimit.attr, | 743 | &loop_attr_sizelimit.attr, |
| 711 | &loop_attr_autoclear.attr, | 744 | &loop_attr_autoclear.attr, |
| 745 | &loop_attr_partscan.attr, | ||
| 712 | NULL, | 746 | NULL, |
| 713 | }; | 747 | }; |
| 714 | 748 | ||
| @@ -729,6 +763,35 @@ static void loop_sysfs_exit(struct loop_device *lo) | |||
| 729 | &loop_attribute_group); | 763 | &loop_attribute_group); |
| 730 | } | 764 | } |
| 731 | 765 | ||
| 766 | static void loop_config_discard(struct loop_device *lo) | ||
| 767 | { | ||
| 768 | struct file *file = lo->lo_backing_file; | ||
| 769 | struct inode *inode = file->f_mapping->host; | ||
| 770 | struct request_queue *q = lo->lo_queue; | ||
| 771 | |||
| 772 | /* | ||
| 773 | * We use punch hole to reclaim the free space used by the | ||
| 774 | * image a.k.a. discard. However we do support discard if | ||
| 775 | * encryption is enabled, because it may give an attacker | ||
| 776 | * useful information. | ||
| 777 | */ | ||
| 778 | if ((!file->f_op->fallocate) || | ||
| 779 | lo->lo_encrypt_key_size) { | ||
| 780 | q->limits.discard_granularity = 0; | ||
| 781 | q->limits.discard_alignment = 0; | ||
| 782 | q->limits.max_discard_sectors = 0; | ||
| 783 | q->limits.discard_zeroes_data = 0; | ||
| 784 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); | ||
| 785 | return; | ||
| 786 | } | ||
| 787 | |||
| 788 | q->limits.discard_granularity = inode->i_sb->s_blocksize; | ||
| 789 | q->limits.discard_alignment = inode->i_sb->s_blocksize; | ||
| 790 | q->limits.max_discard_sectors = UINT_MAX >> 9; | ||
| 791 | q->limits.discard_zeroes_data = 1; | ||
| 792 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); | ||
| 793 | } | ||
| 794 | |||
| 732 | static int loop_set_fd(struct loop_device *lo, fmode_t mode, | 795 | static int loop_set_fd(struct loop_device *lo, fmode_t mode, |
| 733 | struct block_device *bdev, unsigned int arg) | 796 | struct block_device *bdev, unsigned int arg) |
| 734 | { | 797 | { |
| @@ -829,7 +892,9 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, | |||
| 829 | } | 892 | } |
| 830 | lo->lo_state = Lo_bound; | 893 | lo->lo_state = Lo_bound; |
| 831 | wake_up_process(lo->lo_thread); | 894 | wake_up_process(lo->lo_thread); |
| 832 | if (max_part > 0) | 895 | if (part_shift) |
| 896 | lo->lo_flags |= LO_FLAGS_PARTSCAN; | ||
| 897 | if (lo->lo_flags & LO_FLAGS_PARTSCAN) | ||
| 833 | ioctl_by_bdev(bdev, BLKRRPART, 0); | 898 | ioctl_by_bdev(bdev, BLKRRPART, 0); |
| 834 | return 0; | 899 | return 0; |
| 835 | 900 | ||
| @@ -890,10 +955,11 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, | |||
| 890 | return err; | 955 | return err; |
| 891 | } | 956 | } |
| 892 | 957 | ||
| 893 | static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | 958 | static int loop_clr_fd(struct loop_device *lo) |
| 894 | { | 959 | { |
| 895 | struct file *filp = lo->lo_backing_file; | 960 | struct file *filp = lo->lo_backing_file; |
| 896 | gfp_t gfp = lo->old_gfp_mask; | 961 | gfp_t gfp = lo->old_gfp_mask; |
| 962 | struct block_device *bdev = lo->lo_device; | ||
| 897 | 963 | ||
| 898 | if (lo->lo_state != Lo_bound) | 964 | if (lo->lo_state != Lo_bound) |
| 899 | return -ENXIO; | 965 | return -ENXIO; |
| @@ -922,7 +988,6 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
| 922 | lo->lo_offset = 0; | 988 | lo->lo_offset = 0; |
| 923 | lo->lo_sizelimit = 0; | 989 | lo->lo_sizelimit = 0; |
| 924 | lo->lo_encrypt_key_size = 0; | 990 | lo->lo_encrypt_key_size = 0; |
| 925 | lo->lo_flags = 0; | ||
| 926 | lo->lo_thread = NULL; | 991 | lo->lo_thread = NULL; |
| 927 | memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); | 992 | memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); |
| 928 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); | 993 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); |
| @@ -940,8 +1005,11 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
| 940 | lo->lo_state = Lo_unbound; | 1005 | lo->lo_state = Lo_unbound; |
| 941 | /* This is safe: open() is still holding a reference. */ | 1006 | /* This is safe: open() is still holding a reference. */ |
| 942 | module_put(THIS_MODULE); | 1007 | module_put(THIS_MODULE); |
| 943 | if (max_part > 0 && bdev) | 1008 | if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev) |
| 944 | ioctl_by_bdev(bdev, BLKRRPART, 0); | 1009 | ioctl_by_bdev(bdev, BLKRRPART, 0); |
| 1010 | lo->lo_flags = 0; | ||
| 1011 | if (!part_shift) | ||
| 1012 | lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; | ||
| 945 | mutex_unlock(&lo->lo_ctl_mutex); | 1013 | mutex_unlock(&lo->lo_ctl_mutex); |
| 946 | /* | 1014 | /* |
| 947 | * Need not hold lo_ctl_mutex to fput backing file. | 1015 | * Need not hold lo_ctl_mutex to fput backing file. |
| @@ -995,6 +1063,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) | |||
| 995 | if (figure_loop_size(lo)) | 1063 | if (figure_loop_size(lo)) |
| 996 | return -EFBIG; | 1064 | return -EFBIG; |
| 997 | } | 1065 | } |
| 1066 | loop_config_discard(lo); | ||
| 998 | 1067 | ||
| 999 | memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); | 1068 | memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); |
| 1000 | memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); | 1069 | memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); |
| @@ -1010,6 +1079,13 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) | |||
| 1010 | (info->lo_flags & LO_FLAGS_AUTOCLEAR)) | 1079 | (info->lo_flags & LO_FLAGS_AUTOCLEAR)) |
| 1011 | lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; | 1080 | lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; |
| 1012 | 1081 | ||
| 1082 | if ((info->lo_flags & LO_FLAGS_PARTSCAN) && | ||
| 1083 | !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { | ||
| 1084 | lo->lo_flags |= LO_FLAGS_PARTSCAN; | ||
| 1085 | lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; | ||
| 1086 | ioctl_by_bdev(lo->lo_device, BLKRRPART, 0); | ||
| 1087 | } | ||
| 1088 | |||
| 1013 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; | 1089 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; |
| 1014 | lo->lo_init[0] = info->lo_init[0]; | 1090 | lo->lo_init[0] = info->lo_init[0]; |
| 1015 | lo->lo_init[1] = info->lo_init[1]; | 1091 | lo->lo_init[1] = info->lo_init[1]; |
| @@ -1203,7 +1279,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
| 1203 | break; | 1279 | break; |
| 1204 | case LOOP_CLR_FD: | ||
