diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 70 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 16 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 1 |
3 files changed, 51 insertions, 36 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 29af96038e69..426c97aef900 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -928,22 +928,14 @@ void drbd_bm_clear_all(struct drbd_device *device) | |||
928 | spin_unlock_irq(&b->bm_lock); | 928 | spin_unlock_irq(&b->bm_lock); |
929 | } | 929 | } |
930 | 930 | ||
931 | struct bm_aio_ctx { | 931 | static void drbd_bm_aio_ctx_destroy(struct kref *kref) |
932 | struct drbd_device *device; | ||
933 | atomic_t in_flight; | ||
934 | unsigned int done; | ||
935 | unsigned flags; | ||
936 | #define BM_AIO_COPY_PAGES 1 | ||
937 | #define BM_AIO_WRITE_HINTED 2 | ||
938 | #define BM_WRITE_ALL_PAGES 4 | ||
939 | int error; | ||
940 | struct kref kref; | ||
941 | }; | ||
942 | |||
943 | static void bm_aio_ctx_destroy(struct kref *kref) | ||
944 | { | 932 | { |
945 | struct bm_aio_ctx *ctx = container_of(kref, struct bm_aio_ctx, kref); | 933 | struct drbd_bm_aio_ctx *ctx = container_of(kref, struct drbd_bm_aio_ctx, kref); |
934 | unsigned long flags; | ||
946 | 935 | ||
936 | spin_lock_irqsave(&ctx->device->resource->req_lock, flags); | ||
937 | list_del(&ctx->list); | ||
938 | spin_unlock_irqrestore(&ctx->device->resource->req_lock, flags); | ||
947 | put_ldev(ctx->device); | 939 | put_ldev(ctx->device); |
948 | kfree(ctx); | 940 | kfree(ctx); |
949 | } | 941 | } |
@@ -951,7 +943,7 @@ static void bm_aio_ctx_destroy(struct kref *kref) | |||
951 | /* bv_page may be a copy, or may be the original */ | 943 | /* bv_page may be a copy, or may be the original */ |
952 | static void bm_async_io_complete(struct bio *bio, int error) | 944 | static void bm_async_io_complete(struct bio *bio, int error) |
953 | { | 945 | { |
954 | struct bm_aio_ctx *ctx = bio->bi_private; | 946 | struct drbd_bm_aio_ctx *ctx = bio->bi_private; |
955 | struct drbd_device *device = ctx->device; | 947 | struct drbd_device *device = ctx->device; |
956 | struct drbd_bitmap *b = device->bitmap; | 948 | struct drbd_bitmap *b = device->bitmap; |
957 | unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page); | 949 | unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page); |
@@ -994,17 +986,18 @@ static void bm_async_io_complete(struct bio *bio, int error) | |||
994 | if (atomic_dec_and_test(&ctx->in_flight)) { | 986 | if (atomic_dec_and_test(&ctx->in_flight)) { |
995 | ctx->done = 1; | 987 | ctx->done = 1; |
996 | wake_up(&device->misc_wait); | 988 | wake_up(&device->misc_wait); |
997 | kref_put(&ctx->kref, &bm_aio_ctx_destroy); | 989 | kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); |
998 | } | 990 | } |
999 | } | 991 | } |
1000 | 992 | ||
1001 | static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local) | 993 | static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_hold(local) |
1002 | { | 994 | { |
1003 | struct bio *bio = bio_alloc_drbd(GFP_NOIO); | 995 | struct bio *bio = bio_alloc_drbd(GFP_NOIO); |
1004 | struct drbd_device *device = ctx->device; | 996 | struct drbd_device *device = ctx->device; |
1005 | struct drbd_bitmap *b = device->bitmap; | 997 | struct drbd_bitmap *b = device->bitmap; |
1006 | struct page *page; | 998 | struct page *page; |
1007 | unsigned int len; | 999 | unsigned int len; |
1000 | unsigned int rw = (ctx->flags & BM_AIO_READ) ? READ : WRITE; | ||
1008 | 1001 | ||
1009 | sector_t on_disk_sector = | 1002 | sector_t on_disk_sector = |
1010 | device->ldev->md.md_offset + device->ldev->md.bm_offset; | 1003 | device->ldev->md.md_offset + device->ldev->md.bm_offset; |
@@ -1050,9 +1043,9 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must | |||
1050 | /* | 1043 | /* |
1051 | * bm_rw: read/write the whole bitmap from/to its on disk location. | 1044 | * bm_rw: read/write the whole bitmap from/to its on disk location. |
1052 | */ | 1045 | */ |
1053 | static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local) | 1046 | static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned lazy_writeout_upper_idx) __must_hold(local) |
1054 | { | 1047 | { |
1055 | struct bm_aio_ctx *ctx; | 1048 | struct drbd_bm_aio_ctx *ctx; |
1056 | struct drbd_bitmap *b = device->bitmap; | 1049 | struct drbd_bitmap *b = device->bitmap; |
1057 | int num_pages, i, count = 0; | 1050 | int num_pages, i, count = 0; |
1058 | unsigned long now; | 1051 | unsigned long now; |
@@ -1068,12 +1061,13 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1068 | * as we submit copies of pages anyways. | 1061 | * as we submit copies of pages anyways. |
1069 | */ | 1062 | */ |
1070 | 1063 | ||
1071 | ctx = kmalloc(sizeof(struct bm_aio_ctx), GFP_NOIO); | 1064 | ctx = kmalloc(sizeof(struct drbd_bm_aio_ctx), GFP_NOIO); |
1072 | if (!ctx) | 1065 | if (!ctx) |
1073 | return -ENOMEM; | 1066 | return -ENOMEM; |
1074 | 1067 | ||
1075 | *ctx = (struct bm_aio_ctx) { | 1068 | *ctx = (struct drbd_bm_aio_ctx) { |
1076 | .device = device, | 1069 | .device = device, |
1070 | .start_jif = jiffies, | ||
1077 | .in_flight = ATOMIC_INIT(1), | 1071 | .in_flight = ATOMIC_INIT(1), |
1078 | .done = 0, | 1072 | .done = 0, |
1079 | .flags = flags, | 1073 | .flags = flags, |
@@ -1081,7 +1075,7 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1081 | .kref = { ATOMIC_INIT(2) }, | 1075 | .kref = { ATOMIC_INIT(2) }, |
1082 | }; | 1076 | }; |
1083 | 1077 | ||
1084 | if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in bm_aio_ctx_destroy() */ | 1078 | if (!get_ldev_if_state(device, D_ATTACHING)) { /* put is in drbd_bm_aio_ctx_destroy() */ |
1085 | drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n"); | 1079 | drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in bm_rw()\n"); |
1086 | kfree(ctx); | 1080 | kfree(ctx); |
1087 | return -ENODEV; | 1081 | return -ENODEV; |
@@ -1089,9 +1083,13 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1089 | /* Here D_ATTACHING is sufficient since drbd_bm_read() is called only from | 1083 | /* Here D_ATTACHING is sufficient since drbd_bm_read() is called only from |
1090 | drbd_adm_attach(), after device->ldev was assigned. */ | 1084 | drbd_adm_attach(), after device->ldev was assigned. */ |
1091 | 1085 | ||
1092 | if (!ctx->flags) | 1086 | if (0 == (ctx->flags & ~BM_AIO_READ)) |
1093 | WARN_ON(!(BM_LOCKED_MASK & b->bm_flags)); | 1087 | WARN_ON(!(BM_LOCKED_MASK & b->bm_flags)); |
1094 | 1088 | ||
1089 | spin_lock_irq(&device->resource->req_lock); | ||
1090 | list_add_tail(&ctx->list, &device->pending_bitmap_io); | ||
1091 | spin_unlock_irq(&device->resource->req_lock); | ||
1092 | |||
1095 | num_pages = b->bm_number_of_pages; | 1093 | num_pages = b->bm_number_of_pages; |
1096 | 1094 | ||
1097 | now = jiffies; | 1095 | now = jiffies; |
@@ -1101,13 +1099,13 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1101 | /* ignore completely unchanged pages */ | 1099 | /* ignore completely unchanged pages */ |
1102 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) | 1100 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) |
1103 | break; | 1101 | break; |
1104 | if (rw & WRITE) { | 1102 | if (!(flags & BM_AIO_READ)) { |
1105 | if ((flags & BM_AIO_WRITE_HINTED) && | 1103 | if ((flags & BM_AIO_WRITE_HINTED) && |
1106 | !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT, | 1104 | !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT, |
1107 | &page_private(b->bm_pages[i]))) | 1105 | &page_private(b->bm_pages[i]))) |
1108 | continue; | 1106 | continue; |
1109 | 1107 | ||
1110 | if (!(flags & BM_WRITE_ALL_PAGES) && | 1108 | if (!(flags & BM_AIO_WRITE_ALL_PAGES) && |
1111 | bm_test_page_unchanged(b->bm_pages[i])) { | 1109 | bm_test_page_unchanged(b->bm_pages[i])) { |
1112 | dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i); | 1110 | dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i); |
1113 | continue; | 1111 | continue; |
@@ -1121,7 +1119,7 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1121 | } | 1119 | } |
1122 | } | 1120 | } |
1123 | atomic_inc(&ctx->in_flight); | 1121 | atomic_inc(&ctx->in_flight); |
1124 | bm_page_io_async(ctx, i, rw); | 1122 | bm_page_io_async(ctx, i); |
1125 | ++count; | 1123 | ++count; |
1126 | cond_resched(); | 1124 | cond_resched(); |
1127 | } | 1125 | } |
@@ -1137,12 +1135,12 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1137 | if (!atomic_dec_and_test(&ctx->in_flight)) | 1135 | if (!atomic_dec_and_test(&ctx->in_flight)) |
1138 | wait_until_done_or_force_detached(device, device->ldev, &ctx->done); | 1136 | wait_until_done_or_force_detached(device, device->ldev, &ctx->done); |
1139 | else | 1137 | else |
1140 | kref_put(&ctx->kref, &bm_aio_ctx_destroy); | 1138 | kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); |
1141 | 1139 | ||
1142 | /* summary for global bitmap IO */ | 1140 | /* summary for global bitmap IO */ |
1143 | if (flags == 0) | 1141 | if (flags == 0) |
1144 | drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n", | 1142 | drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n", |
1145 | rw == WRITE ? "WRITE" : "READ", | 1143 | (flags & BM_AIO_READ) ? "READ" : "WRITE", |
1146 | count, jiffies - now); | 1144 | count, jiffies - now); |
1147 | 1145 | ||
1148 | if (ctx->error) { | 1146 | if (ctx->error) { |
@@ -1155,18 +1153,18 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1155 | err = -EIO; /* Disk timeout/force-detach during IO... */ | 1153 | err = -EIO; /* Disk timeout/force-detach during IO... */ |
1156 | 1154 | ||
1157 | now = jiffies; | 1155 | now = jiffies; |
1158 | if (rw == READ) { | 1156 | if (flags & BM_AIO_READ) { |
1159 | b->bm_set = bm_count_bits(b); | 1157 | b->bm_set = bm_count_bits(b); |
1160 | drbd_info(device, "recounting of set bits took additional %lu jiffies\n", | 1158 | drbd_info(device, "recounting of set bits took additional %lu jiffies\n", |
1161 | jiffies - now); | 1159 | jiffies - now); |
1162 | } | 1160 | } |
1163 | now = b->bm_set; | 1161 | now = b->bm_set; |
1164 | 1162 | ||
1165 | if (flags == 0) | 1163 | if ((flags & ~BM_AIO_READ) == 0) |
1166 | drbd_info(device, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n", | 1164 | drbd_info(device, "%s (%lu bits) marked out-of-sync by on disk bit-map.\n", |
1167 | ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now); | 1165 | ppsize(ppb, now << (BM_BLOCK_SHIFT-10)), now); |
1168 | 1166 | ||
1169 | kref_put(&ctx->kref, &bm_aio_ctx_destroy); | 1167 | kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); |
1170 | return err; | 1168 | return err; |
1171 | } | 1169 | } |
1172 | 1170 | ||
@@ -1176,7 +1174,7 @@ static int bm_rw(struct drbd_device *device, int rw, unsigned flags, unsigned la | |||
1176 | */ | 1174 | */ |
1177 | int drbd_bm_read(struct drbd_device *device) __must_hold(local) | 1175 | int drbd_bm_read(struct drbd_device *device) __must_hold(local) |
1178 | { | 1176 | { |
1179 | return bm_rw(device, READ, 0, 0); | 1177 | return bm_rw(device, BM_AIO_READ, 0); |
1180 | } | 1178 | } |
1181 | 1179 | ||
1182 | /** | 1180 | /** |
@@ -1187,7 +1185,7 @@ int drbd_bm_read(struct drbd_device *device) __must_hold(local) | |||
1187 | */ | 1185 | */ |
1188 | int drbd_bm_write(struct drbd_device *device) __must_hold(local) | 1186 | int drbd_bm_write(struct drbd_device *device) __must_hold(local) |
1189 | { | 1187 | { |
1190 | return bm_rw(device, WRITE, 0, 0); | 1188 | return bm_rw(device, 0, 0); |
1191 | } | 1189 | } |
1192 | 1190 | ||
1193 | /** | 1191 | /** |
@@ -1198,7 +1196,7 @@ int drbd_bm_write(struct drbd_device *device) __must_hold(local) | |||
1198 | */ | 1196 | */ |
1199 | int drbd_bm_write_all(struct drbd_device *device) __must_hold(local) | 1197 | int drbd_bm_write_all(struct drbd_device *device) __must_hold(local) |
1200 | { | 1198 | { |
1201 | return bm_rw(device, WRITE, BM_WRITE_ALL_PAGES, 0); | 1199 | return bm_rw(device, BM_AIO_WRITE_ALL_PAGES, 0); |
1202 | } | 1200 | } |
1203 | 1201 | ||
1204 | /** | 1202 | /** |
@@ -1224,7 +1222,7 @@ int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_ho | |||
1224 | */ | 1222 | */ |
1225 | int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local) | 1223 | int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local) |
1226 | { | 1224 | { |
1227 | return bm_rw(device, WRITE, BM_AIO_COPY_PAGES, 0); | 1225 | return bm_rw(device, BM_AIO_COPY_PAGES, 0); |
1228 | } | 1226 | } |
1229 | 1227 | ||
1230 | /** | 1228 | /** |
@@ -1233,7 +1231,7 @@ int drbd_bm_write_copy_pages(struct drbd_device *device) __must_hold(local) | |||
1233 | */ | 1231 | */ |
1234 | int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local) | 1232 | int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local) |
1235 | { | 1233 | { |
1236 | return bm_rw(device, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0); | 1234 | return bm_rw(device, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0); |
1237 | } | 1235 | } |
1238 | 1236 | ||
1239 | /* NOTE | 1237 | /* NOTE |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c7a409f3aaf8..40c816ce8d75 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -777,6 +777,7 @@ struct drbd_peer_device { | |||
777 | struct drbd_device { | 777 | struct drbd_device { |
778 | struct drbd_resource *resource; | 778 | struct drbd_resource *resource; |
779 | struct list_head peer_devices; | 779 | struct list_head peer_devices; |
780 | struct list_head pending_bitmap_io; | ||
780 | int vnr; /* volume number within the connection */ | 781 | int vnr; /* volume number within the connection */ |
781 | struct kref kref; | 782 | struct kref kref; |
782 | 783 | ||
@@ -918,6 +919,21 @@ struct drbd_device { | |||
918 | struct submit_worker submit; | 919 | struct submit_worker submit; |
919 | }; | 920 | }; |
920 | 921 | ||
922 | struct drbd_bm_aio_ctx { | ||
923 | struct drbd_device *device; | ||
924 | struct list_head list; /* on device->pending_bitmap_io */; | ||
925 | unsigned long start_jif; | ||
926 | atomic_t in_flight; | ||
927 | unsigned int done; | ||
928 | unsigned flags; | ||
929 | #define BM_AIO_COPY_PAGES 1 | ||
930 | #define BM_AIO_WRITE_HINTED 2 | ||
931 | #define BM_AIO_WRITE_ALL_PAGES 4 | ||
932 | #define BM_AIO_READ 8 | ||
933 | int error; | ||
934 | struct kref kref; | ||
935 | }; | ||
936 | |||
921 | struct drbd_config_context { | 937 | struct drbd_config_context { |
922 | /* assigned from drbd_genlmsghdr */ | 938 | /* assigned from drbd_genlmsghdr */ |
923 | unsigned int minor; | 939 | unsigned int minor; |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index ad7c0e8843c4..922d631c10b3 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -2793,6 +2793,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig | |||
2793 | kref_get(&device->kref); | 2793 | kref_get(&device->kref); |
2794 | 2794 | ||
2795 | INIT_LIST_HEAD(&device->peer_devices); | 2795 | INIT_LIST_HEAD(&device->peer_devices); |
2796 | INIT_LIST_HEAD(&device->pending_bitmap_io); | ||
2796 | for_each_connection(connection, resource) { | 2797 | for_each_connection(connection, resource) { |
2797 | peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL); | 2798 | peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL); |
2798 | if (!peer_device) | 2799 | if (!peer_device) |