diff options
-rw-r--r-- | drivers/block/nbd.c | 92 |
1 files changed, 37 insertions, 55 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 99a0dd58602e..d5828b9dbfef 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -120,11 +120,6 @@ static inline struct device *nbd_to_dev(struct nbd_device *nbd) | |||
120 | return disk_to_dev(nbd->disk); | 120 | return disk_to_dev(nbd->disk); |
121 | } | 121 | } |
122 | 122 | ||
123 | static bool nbd_is_connected(struct nbd_device *nbd) | ||
124 | { | ||
125 | return !!nbd->task_recv; | ||
126 | } | ||
127 | |||
128 | static const char *nbdcmd_to_ascii(int cmd) | 123 | static const char *nbdcmd_to_ascii(int cmd) |
129 | { | 124 | { |
130 | switch (cmd) { | 125 | switch (cmd) { |
@@ -160,36 +155,30 @@ static void nbd_mark_nsock_dead(struct nbd_sock *nsock) | |||
160 | nsock->sent = 0; | 155 | nsock->sent = 0; |
161 | } | 156 | } |
162 | 157 | ||
163 | static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev) | 158 | static void nbd_size_clear(struct nbd_device *nbd) |
164 | { | 159 | { |
165 | if (nbd->config->bytesize) { | 160 | if (nbd->config->bytesize) { |
166 | if (bdev->bd_openers <= 1) | ||
167 | bd_set_size(bdev, 0); | ||
168 | set_capacity(nbd->disk, 0); | 161 | set_capacity(nbd->disk, 0); |
169 | kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); | 162 | kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); |
170 | } | 163 | } |
171 | |||
172 | return 0; | ||
173 | } | 164 | } |
174 | 165 | ||
175 | static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev) | 166 | static void nbd_size_update(struct nbd_device *nbd) |
176 | { | 167 | { |
177 | struct nbd_config *config = nbd->config; | 168 | struct nbd_config *config = nbd->config; |
178 | blk_queue_logical_block_size(nbd->disk->queue, config->blksize); | 169 | blk_queue_logical_block_size(nbd->disk->queue, config->blksize); |
179 | blk_queue_physical_block_size(nbd->disk->queue, config->blksize); | 170 | blk_queue_physical_block_size(nbd->disk->queue, config->blksize); |
180 | bd_set_size(bdev, config->bytesize); | ||
181 | set_capacity(nbd->disk, config->bytesize >> 9); | 171 | set_capacity(nbd->disk, config->bytesize >> 9); |
182 | kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); | 172 | kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); |
183 | } | 173 | } |
184 | 174 | ||
185 | static void nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, | 175 | static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize, |
186 | loff_t blocksize, loff_t nr_blocks) | 176 | loff_t nr_blocks) |
187 | { | 177 | { |
188 | struct nbd_config *config = nbd->config; | 178 | struct nbd_config *config = nbd->config; |
189 | config->blksize = blocksize; | 179 | config->blksize = blocksize; |
190 | config->bytesize = blocksize * nr_blocks; | 180 | config->bytesize = blocksize * nr_blocks; |
191 | if (nbd_is_connected(nbd)) | 181 | nbd_size_update(nbd); |
192 | nbd_size_update(nbd, bdev); | ||
193 | } | 182 | } |
194 | 183 | ||
195 | static void nbd_end_request(struct nbd_cmd *cmd) | 184 | static void nbd_end_request(struct nbd_cmd *cmd) |
@@ -739,8 +728,7 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
739 | return ret; | 728 | return ret; |
740 | } | 729 | } |
741 | 730 | ||
742 | static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev, | 731 | static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg) |
743 | unsigned long arg) | ||
744 | { | 732 | { |
745 | struct nbd_config *config = nbd->config; | 733 | struct nbd_config *config = nbd->config; |
746 | struct socket *sock; | 734 | struct socket *sock; |
@@ -783,8 +771,6 @@ static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev, | |||
783 | nsock->sent = 0; | 771 | nsock->sent = 0; |
784 | socks[config->num_connections++] = nsock; | 772 | socks[config->num_connections++] = nsock; |
785 | 773 | ||
786 | if (max_part) | ||
787 | bdev->bd_invalidated = 1; | ||
788 | return 0; | 774 | return 0; |
789 | } | 775 | } |
790 | 776 | ||
@@ -800,19 +786,20 @@ static void nbd_bdev_reset(struct block_device *bdev) | |||
800 | { | 786 | { |
801 | if (bdev->bd_openers > 1) | 787 | if (bdev->bd_openers > 1) |
802 | return; | 788 | return; |
803 | set_device_ro(bdev, false); | 789 | bd_set_size(bdev, 0); |
804 | bdev->bd_inode->i_size = 0; | ||
805 | if (max_part > 0) { | 790 | if (max_part > 0) { |
806 | blkdev_reread_part(bdev); | 791 | blkdev_reread_part(bdev); |
807 | bdev->bd_invalidated = 1; | 792 | bdev->bd_invalidated = 1; |
808 | } | 793 | } |
809 | } | 794 | } |
810 | 795 | ||
811 | static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) | 796 | static void nbd_parse_flags(struct nbd_device *nbd) |
812 | { | 797 | { |
813 | struct nbd_config *config = nbd->config; | 798 | struct nbd_config *config = nbd->config; |
814 | if (config->flags & NBD_FLAG_READ_ONLY) | 799 | if (config->flags & NBD_FLAG_READ_ONLY) |
815 | set_device_ro(bdev, true); | 800 | set_disk_ro(nbd->disk, true); |
801 | else | ||
802 | set_disk_ro(nbd->disk, false); | ||
816 | if (config->flags & NBD_FLAG_SEND_TRIM) | 803 | if (config->flags & NBD_FLAG_SEND_TRIM) |
817 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); | 804 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); |
818 | if (config->flags & NBD_FLAG_SEND_FLUSH) | 805 | if (config->flags & NBD_FLAG_SEND_FLUSH) |
@@ -841,52 +828,36 @@ static void send_disconnects(struct nbd_device *nbd) | |||
841 | } | 828 | } |
842 | } | 829 | } |
843 | 830 | ||
844 | static int nbd_disconnect(struct nbd_device *nbd, struct block_device *bdev) | 831 | static int nbd_disconnect(struct nbd_device *nbd) |
845 | { | 832 | { |
846 | struct nbd_config *config = nbd->config; | 833 | struct nbd_config *config = nbd->config; |
847 | 834 | ||
848 | dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); | 835 | dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); |
849 | mutex_unlock(&nbd->config_lock); | ||
850 | fsync_bdev(bdev); | ||
851 | mutex_lock(&nbd->config_lock); | ||
852 | |||
853 | if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED, | 836 | if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED, |
854 | &config->runtime_flags)) | 837 | &config->runtime_flags)) |
855 | send_disconnects(nbd); | 838 | send_disconnects(nbd); |
856 | return 0; | 839 | return 0; |
857 | } | 840 | } |
858 | 841 | ||
859 | static int nbd_clear_sock(struct nbd_device *nbd, struct block_device *bdev) | 842 | static void nbd_clear_sock(struct nbd_device *nbd) |
860 | { | 843 | { |
861 | sock_shutdown(nbd); | 844 | sock_shutdown(nbd); |
862 | nbd_clear_que(nbd); | 845 | nbd_clear_que(nbd); |
863 | |||
864 | __invalidate_device(bdev, true); | ||
865 | nbd_bdev_reset(bdev); | ||
866 | nbd->task_setup = NULL; | 846 | nbd->task_setup = NULL; |
867 | return 0; | ||
868 | } | 847 | } |
869 | 848 | ||
870 | static void nbd_config_put(struct nbd_device *nbd) | 849 | static void nbd_config_put(struct nbd_device *nbd) |
871 | { | 850 | { |
872 | if (refcount_dec_and_mutex_lock(&nbd->config_refs, | 851 | if (refcount_dec_and_mutex_lock(&nbd->config_refs, |
873 | &nbd->config_lock)) { | 852 | &nbd->config_lock)) { |
874 | struct block_device *bdev; | ||
875 | struct nbd_config *config = nbd->config; | 853 | struct nbd_config *config = nbd->config; |
876 | |||
877 | bdev = bdget_disk(nbd->disk, 0); | ||
878 | if (!bdev) { | ||
879 | mutex_unlock(&nbd->config_lock); | ||
880 | return; | ||
881 | } | ||
882 | |||
883 | nbd_dev_dbg_close(nbd); | 854 | nbd_dev_dbg_close(nbd); |
884 | nbd_size_clear(nbd, bdev); | 855 | nbd_size_clear(nbd); |
885 | if (test_and_clear_bit(NBD_HAS_PID_FILE, | 856 | if (test_and_clear_bit(NBD_HAS_PID_FILE, |
886 | &config->runtime_flags)) | 857 | &config->runtime_flags)) |
887 | device_remove_file(disk_to_dev(nbd->disk), &pid_attr); | 858 | device_remove_file(disk_to_dev(nbd->disk), &pid_attr); |
888 | nbd->task_recv = NULL; | 859 | nbd->task_recv = NULL; |
889 | nbd_clear_sock(nbd, bdev); | 860 | nbd_clear_sock(nbd); |
890 | if (config->num_connections) { | 861 | if (config->num_connections) { |
891 | int i; | 862 | int i; |
892 | for (i = 0; i < config->num_connections; i++) { | 863 | for (i = 0; i < config->num_connections; i++) { |
@@ -897,7 +868,6 @@ static void nbd_config_put(struct nbd_device *nbd) | |||
897 | } | 868 | } |
898 | nbd_reset(nbd); | 869 | nbd_reset(nbd); |
899 | mutex_unlock(&nbd->config_lock); | 870 | mutex_unlock(&nbd->config_lock); |
900 | bdput(bdev); | ||
901 | module_put(THIS_MODULE); | 871 | module_put(THIS_MODULE); |
902 | } | 872 | } |
903 | } | 873 | } |
@@ -912,27 +882,30 @@ static int nbd_start_device(struct nbd_device *nbd, struct block_device *bdev) | |||
912 | return -EBUSY; | 882 | return -EBUSY; |
913 | if (!config->socks) | 883 | if (!config->socks) |
914 | return -EINVAL; | 884 | return -EINVAL; |
915 | |||
916 | if (num_connections > 1 && | 885 | if (num_connections > 1 && |
917 | !(config->flags & NBD_FLAG_CAN_MULTI_CONN)) { | 886 | !(config->flags & NBD_FLAG_CAN_MULTI_CONN)) { |
918 | dev_err(disk_to_dev(nbd->disk), "server does not support multiple connections per device.\n"); | 887 | dev_err(disk_to_dev(nbd->disk), "server does not support multiple connections per device.\n"); |
919 | return -EINVAL; | 888 | return -EINVAL; |
920 | } | 889 | } |
921 | 890 | ||
891 | if (max_part) | ||
892 | bdev->bd_invalidated = 1; | ||
922 | blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); | 893 | blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); |
923 | nbd->task_recv = current; | 894 | nbd->task_recv = current; |
924 | mutex_unlock(&nbd->config_lock); | 895 | mutex_unlock(&nbd->config_lock); |
925 | 896 | ||
926 | nbd_parse_flags(nbd, bdev); | 897 | nbd_parse_flags(nbd); |
927 | 898 | ||
928 | error = device_create_file(disk_to_dev(nbd->disk), &pid_attr); | 899 | error = device_create_file(disk_to_dev(nbd->disk), &pid_attr); |
929 | if (error) { | 900 | if (error) { |
930 | dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); | 901 | dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); |
931 | return error; | 902 | return error; |
932 | } | 903 | } |
933 | set_bit(NBD_HAS_PID_FILE, &config->runtime_flags); | ||
934 | 904 | ||
935 | nbd_size_update(nbd, bdev); | 905 | set_bit(NBD_HAS_PID_FILE, &config->runtime_flags); |
906 | if (max_part) | ||
907 | bdev->bd_invalidated = 1; | ||
908 | bd_set_size(bdev, config->bytesize); | ||
936 | 909 | ||
937 | nbd_dev_dbg_init(nbd); | 910 | nbd_dev_dbg_init(nbd); |
938 | for (i = 0; i < num_connections; i++) { | 911 | for (i = 0; i < num_connections; i++) { |
@@ -965,6 +938,14 @@ static int nbd_start_device(struct nbd_device *nbd, struct block_device *bdev) | |||
965 | return error; | 938 | return error; |
966 | } | 939 | } |
967 | 940 | ||
941 | static void nbd_clear_sock_ioctl(struct nbd_device *nbd, | ||
942 | struct block_device *bdev) | ||
943 | { | ||
944 | nbd_clear_sock(nbd); | ||
945 | kill_bdev(bdev); | ||
946 | nbd_bdev_reset(bdev); | ||
947 | } | ||
948 | |||
968 | /* Must be called with config_lock held */ | 949 | /* Must be called with config_lock held */ |
969 | static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | 950 | static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, |
970 | unsigned int cmd, unsigned long arg) | 951 | unsigned int cmd, unsigned long arg) |
@@ -973,21 +954,22 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | |||
973 | 954 | ||
974 | switch (cmd) { | 955 | switch (cmd) { |
975 | case NBD_DISCONNECT: | 956 | case NBD_DISCONNECT: |
976 | return nbd_disconnect(nbd, bdev); | 957 | return nbd_disconnect(nbd); |
977 | case NBD_CLEAR_SOCK: | 958 | case NBD_CLEAR_SOCK: |
978 | return nbd_clear_sock(nbd, bdev); | 959 | nbd_clear_sock_ioctl(nbd, bdev); |
960 | return 0; | ||
979 | case NBD_SET_SOCK: | 961 | case NBD_SET_SOCK: |
980 | return nbd_add_socket(nbd, bdev, arg); | 962 | return nbd_add_socket(nbd, arg); |
981 | case NBD_SET_BLKSIZE: | 963 | case NBD_SET_BLKSIZE: |
982 | nbd_size_set(nbd, bdev, arg, | 964 | nbd_size_set(nbd, arg, |
983 | div_s64(config->bytesize, arg)); | 965 | div_s64(config->bytesize, arg)); |
984 | return 0; | 966 | return 0; |
985 | case NBD_SET_SIZE: | 967 | case NBD_SET_SIZE: |
986 | nbd_size_set(nbd, bdev, config->blksize, | 968 | nbd_size_set(nbd, config->blksize, |
987 | div_s64(arg, config->blksize)); | 969 | div_s64(arg, config->blksize)); |
988 | return 0; | 970 | return 0; |
989 | case NBD_SET_SIZE_BLOCKS: | 971 | case NBD_SET_SIZE_BLOCKS: |
990 | nbd_size_set(nbd, bdev, config->blksize, arg); | 972 | nbd_size_set(nbd, config->blksize, arg); |
991 | return 0; | 973 | return 0; |
992 | case NBD_SET_TIMEOUT: | 974 | case NBD_SET_TIMEOUT: |
993 | if (arg) { | 975 | if (arg) { |