diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2014-04-01 17:53:30 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2014-07-10 12:35:10 -0400 |
commit | e37d2438d8e5e4c1225cf94d45347fa207835447 (patch) | |
tree | bd1756066196e9922c476f75759f4846455c2c63 /drivers/block | |
parent | a8ba0d606933c34c13ea971491a7e0dfa50208ef (diff) |
drbd: track meta data IO intent, start and submit time
For diagnostic purposes, track intent, start time
and latest submit time of meta data IO.
Move separate members from struct drbd_device
into the embeded struct drbd_md_io.
s/md_io_(page|in_use)/md_io.\1/
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 26 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 9 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 14 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 9 |
5 files changed, 35 insertions, 27 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 5f82a36f799d..d7e80663187c 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c | |||
@@ -92,20 +92,26 @@ struct __packed al_transaction_on_disk { | |||
92 | __be32 context[AL_CONTEXT_PER_TRANSACTION]; | 92 | __be32 context[AL_CONTEXT_PER_TRANSACTION]; |
93 | }; | 93 | }; |
94 | 94 | ||
95 | void *drbd_md_get_buffer(struct drbd_device *device) | 95 | void *drbd_md_get_buffer(struct drbd_device *device, const char *intent) |
96 | { | 96 | { |
97 | int r; | 97 | int r; |
98 | 98 | ||
99 | wait_event(device->misc_wait, | 99 | wait_event(device->misc_wait, |
100 | (r = atomic_cmpxchg(&device->md_io_in_use, 0, 1)) == 0 || | 100 | (r = atomic_cmpxchg(&device->md_io.in_use, 0, 1)) == 0 || |
101 | device->state.disk <= D_FAILED); | 101 | device->state.disk <= D_FAILED); |
102 | 102 | ||
103 | return r ? NULL : page_address(device->md_io_page); | 103 | if (r) |
104 | return NULL; | ||
105 | |||
106 | device->md_io.current_use = intent; | ||
107 | device->md_io.start_jif = jiffies; | ||
108 | device->md_io.submit_jif = device->md_io.start_jif - 1; | ||
109 | return page_address(device->md_io.page); | ||
104 | } | 110 | } |
105 | 111 | ||
106 | void drbd_md_put_buffer(struct drbd_device *device) | 112 | void drbd_md_put_buffer(struct drbd_device *device) |
107 | { | 113 | { |
108 | if (atomic_dec_and_test(&device->md_io_in_use)) | 114 | if (atomic_dec_and_test(&device->md_io.in_use)) |
109 | wake_up(&device->misc_wait); | 115 | wake_up(&device->misc_wait); |
110 | } | 116 | } |
111 | 117 | ||
@@ -150,7 +156,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, | |||
150 | err = -EIO; | 156 | err = -EIO; |
151 | if (bio_add_page(bio, page, size, 0) != size) | 157 | if (bio_add_page(bio, page, size, 0) != size) |
152 | goto out; | 158 | goto out; |
153 | bio->bi_private = &device->md_io; | 159 | bio->bi_private = device; |
154 | bio->bi_end_io = drbd_md_io_complete; | 160 | bio->bi_end_io = drbd_md_io_complete; |
155 | bio->bi_rw = rw; | 161 | bio->bi_rw = rw; |
156 | 162 | ||
@@ -165,7 +171,8 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, | |||
165 | } | 171 | } |
166 | 172 | ||
167 | bio_get(bio); /* one bio_put() is in the completion handler */ | 173 | bio_get(bio); /* one bio_put() is in the completion handler */ |
168 | atomic_inc(&device->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */ | 174 | atomic_inc(&device->md_io.in_use); /* drbd_md_put_buffer() is in the completion handler */ |
175 | device->md_io.submit_jif = jiffies; | ||
169 | if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) | 176 | if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) |
170 | bio_endio(bio, -EIO); | 177 | bio_endio(bio, -EIO); |
171 | else | 178 | else |
@@ -183,9 +190,9 @@ int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bd | |||
183 | sector_t sector, int rw) | 190 | sector_t sector, int rw) |
184 | { | 191 | { |
185 | int err; | 192 | int err; |
186 | struct page *iop = device->md_io_page; | 193 | struct page *iop = device->md_io.page; |
187 | 194 | ||
188 | D_ASSERT(device, atomic_read(&device->md_io_in_use) == 1); | 195 | D_ASSERT(device, atomic_read(&device->md_io.in_use) == 1); |
189 | 196 | ||
190 | BUG_ON(!bdev->md_bdev); | 197 | BUG_ON(!bdev->md_bdev); |
191 | 198 | ||
@@ -465,7 +472,8 @@ int al_write_transaction(struct drbd_device *device) | |||
465 | return -EIO; | 472 | return -EIO; |
466 | } | 473 | } |
467 | 474 | ||
468 | buffer = drbd_md_get_buffer(device); /* protects md_io_buffer, al_tr_cycle, ... */ | 475 | /* protects md_io_buffer, al_tr_cycle, ... */ |
476 | buffer = drbd_md_get_buffer(device, __func__); | ||
469 | if (!buffer) { | 477 | if (!buffer) { |
470 | drbd_err(device, "disk failed while waiting for md_io buffer\n"); | 478 | drbd_err(device, "disk failed while waiting for md_io buffer\n"); |
471 | put_ldev(device); | 479 | put_ldev(device); |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index d85f43c9ef56..3f8281bbea53 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -542,6 +542,11 @@ struct drbd_backing_dev { | |||
542 | }; | 542 | }; |
543 | 543 | ||
544 | struct drbd_md_io { | 544 | struct drbd_md_io { |
545 | struct page *page; | ||
546 | unsigned long start_jif; /* last call to drbd_md_get_buffer */ | ||
547 | unsigned long submit_jif; /* last _drbd_md_sync_page_io() submit */ | ||
548 | const char *current_use; | ||
549 | atomic_t in_use; | ||
545 | unsigned int done; | 550 | unsigned int done; |
546 | int error; | 551 | int error; |
547 | }; | 552 | }; |
@@ -795,9 +800,7 @@ struct drbd_device { | |||
795 | atomic_t pp_in_use; /* allocated from page pool */ | 800 | atomic_t pp_in_use; /* allocated from page pool */ |
796 | atomic_t pp_in_use_by_net; /* sendpage()d, still referenced by tcp */ | 801 | atomic_t pp_in_use_by_net; /* sendpage()d, still referenced by tcp */ |
797 | wait_queue_head_t ee_wait; | 802 | wait_queue_head_t ee_wait; |
798 | struct page *md_io_page; /* one page buffer for md_io */ | ||
799 | struct drbd_md_io md_io; | 803 | struct drbd_md_io md_io; |
800 | atomic_t md_io_in_use; /* protects the md_io, md_io_page and md_io_tmpp */ | ||
801 | spinlock_t al_lock; | 804 | spinlock_t al_lock; |
802 | wait_queue_head_t al_wait; | 805 | wait_queue_head_t al_wait; |
803 | struct lru_cache *act_log; /* activity log */ | 806 | struct lru_cache *act_log; /* activity log */ |
@@ -1336,7 +1339,7 @@ extern void resume_next_sg(struct drbd_device *device); | |||
1336 | extern void suspend_other_sg(struct drbd_device *device); | 1339 | extern void suspend_other_sg(struct drbd_device *device); |
1337 | extern int drbd_resync_finished(struct drbd_device *device); | 1340 | extern int drbd_resync_finished(struct drbd_device *device); |
1338 | /* maybe rather drbd_main.c ? */ | 1341 | /* maybe rather drbd_main.c ? */ |
1339 | extern void *drbd_md_get_buffer(struct drbd_device *device); | 1342 | extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent); |
1340 | extern void drbd_md_put_buffer(struct drbd_device *device); | 1343 | extern void drbd_md_put_buffer(struct drbd_device *device); |
1341 | extern int drbd_md_sync_page_io(struct drbd_device *device, | 1344 | extern int drbd_md_sync_page_io(struct drbd_device *device, |
1342 | struct drbd_backing_dev *bdev, sector_t sector, int rw); | 1345 | struct drbd_backing_dev *bdev, sector_t sector, int rw); |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 56cf11b60cb8..3ab74619c8eb 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -1916,7 +1916,7 @@ void drbd_init_set_defaults(struct drbd_device *device) | |||
1916 | atomic_set(&device->rs_sect_in, 0); | 1916 | atomic_set(&device->rs_sect_in, 0); |
1917 | atomic_set(&device->rs_sect_ev, 0); | 1917 | atomic_set(&device->rs_sect_ev, 0); |
1918 | atomic_set(&device->ap_in_flight, 0); | 1918 | atomic_set(&device->ap_in_flight, 0); |
1919 | atomic_set(&device->md_io_in_use, 0); | 1919 | atomic_set(&device->md_io.in_use, 0); |
1920 | 1920 | ||
1921 | mutex_init(&device->own_state_mutex); | 1921 | mutex_init(&device->own_state_mutex); |
1922 | device->state_mutex = &device->own_state_mutex; | 1922 | device->state_mutex = &device->own_state_mutex; |
@@ -2187,7 +2187,7 @@ void drbd_destroy_device(struct kref *kref) | |||
2187 | 2187 | ||
2188 | if (device->bitmap) /* should no longer be there. */ | 2188 | if (device->bitmap) /* should no longer be there. */ |
2189 | drbd_bm_cleanup(device); | 2189 | drbd_bm_cleanup(device); |
2190 | __free_page(device->md_io_page); | 2190 | __free_page(device->md_io.page); |
2191 | put_disk(device->vdisk); | 2191 | put_disk(device->vdisk); |
2192 | blk_cleanup_queue(device->rq_queue); | 2192 | blk_cleanup_queue(device->rq_queue); |
2193 | kfree(device->rs_plan_s); | 2193 | kfree(device->rs_plan_s); |
@@ -2756,8 +2756,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig | |||
2756 | blk_queue_merge_bvec(q, drbd_merge_bvec); | 2756 | blk_queue_merge_bvec(q, drbd_merge_bvec); |
2757 | q->queue_lock = &resource->req_lock; | 2757 | q->queue_lock = &resource->req_lock; |
2758 | 2758 | ||
2759 | device->md_io_page = alloc_page(GFP_KERNEL); | 2759 | device->md_io.page = alloc_page(GFP_KERNEL); |
2760 | if (!device->md_io_page) | 2760 | if (!device->md_io.page) |
2761 | goto out_no_io_page; | 2761 | goto out_no_io_page; |
2762 | 2762 | ||
2763 | if (drbd_bm_init(device)) | 2763 | if (drbd_bm_init(device)) |
@@ -2845,7 +2845,7 @@ out_idr_remove_minor: | |||
2845 | out_no_minor_idr: | 2845 | out_no_minor_idr: |
2846 | drbd_bm_cleanup(device); | 2846 | drbd_bm_cleanup(device); |
2847 | out_no_bitmap: | 2847 | out_no_bitmap: |
2848 | __free_page(device->md_io_page); | 2848 | __free_page(device->md_io.page); |
2849 | out_no_io_page: | 2849 | out_no_io_page: |
2850 | put_disk(disk); | 2850 | put_disk(disk); |
2851 | out_no_disk: | 2851 | out_no_disk: |
@@ -3079,7 +3079,7 @@ void drbd_md_sync(struct drbd_device *device) | |||
3079 | if (!get_ldev_if_state(device, D_FAILED)) | 3079 | if (!get_ldev_if_state(device, D_FAILED)) |
3080 | return; | 3080 | return; |
3081 | 3081 | ||
3082 | buffer = drbd_md_get_buffer(device); | 3082 | buffer = drbd_md_get_buffer(device, __func__); |
3083 | if (!buffer) | 3083 | if (!buffer) |
3084 | goto out; | 3084 | goto out; |
3085 | 3085 | ||
@@ -3239,7 +3239,7 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev) | |||
3239 | if (device->state.disk != D_DISKLESS) | 3239 | if (device->state.disk != D_DISKLESS) |
3240 | return ERR_DISK_CONFIGURED; | 3240 | return ERR_DISK_CONFIGURED; |
3241 | 3241 | ||
3242 | buffer = drbd_md_get_buffer(device); | 3242 | buffer = drbd_md_get_buffer(device, __func__); |
3243 | if (!buffer) | 3243 | if (!buffer) |
3244 | return ERR_NOMEM; | 3244 | return ERR_NOMEM; |
3245 | 3245 | ||
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index c2e047f89bcf..7fcdc54bf65a 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -887,7 +887,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct | |||
887 | * still lock the act_log to not trigger ASSERTs there. | 887 | * still lock the act_log to not trigger ASSERTs there. |
888 | */ | 888 | */ |
889 | drbd_suspend_io(device); | 889 | drbd_suspend_io(device); |
890 | buffer = drbd_md_get_buffer(device); /* Lock meta-data IO */ | 890 | buffer = drbd_md_get_buffer(device, __func__); /* Lock meta-data IO */ |
891 | if (!buffer) { | 891 | if (!buffer) { |
892 | drbd_resume_io(device); | 892 | drbd_resume_io(device); |
893 | return DS_ERROR; | 893 | return DS_ERROR; |
@@ -1899,7 +1899,7 @@ static int adm_detach(struct drbd_device *device, int force) | |||
1899 | } | 1899 | } |
1900 | 1900 | ||
1901 | drbd_suspend_io(device); /* so no-one is stuck in drbd_al_begin_io */ | 1901 | drbd_suspend_io(device); /* so no-one is stuck in drbd_al_begin_io */ |
1902 | drbd_md_get_buffer(device); /* make sure there is no in-flight meta-data IO */ | 1902 | drbd_md_get_buffer(device, __func__); /* make sure there is no in-flight meta-data IO */ |
1903 | retcode = drbd_request_state(device, NS(disk, D_FAILED)); | 1903 | retcode = drbd_request_state(device, NS(disk, D_FAILED)); |
1904 | drbd_md_put_buffer(device); | 1904 | drbd_md_put_buffer(device); |
1905 | /* D_FAILED will transition to DISKLESS. */ | 1905 | /* D_FAILED will transition to DISKLESS. */ |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ad57129289b5..3978d9ec6f00 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -67,13 +67,10 @@ rwlock_t global_state_lock; | |||
67 | */ | 67 | */ |
68 | void drbd_md_io_complete(struct bio *bio, int error) | 68 | void drbd_md_io_complete(struct bio *bio, int error) |
69 | { | 69 | { |
70 | struct drbd_md_io *md_io; | ||
71 | struct drbd_device *device; | 70 | struct drbd_device *device; |
72 | 71 | ||
73 | md_io = (struct drbd_md_io *)bio->bi_private; | 72 | device = bio->bi_private; |
74 | device = container_of(md_io, struct drbd_device, md_io); | 73 | device->md_io.error = error; |
75 | |||
76 | md_io->error = error; | ||
77 | 74 | ||
78 | /* We grabbed an extra reference in _drbd_md_sync_page_io() to be able | 75 | /* We grabbed an extra reference in _drbd_md_sync_page_io() to be able |
79 | * to timeout on the lower level device, and eventually detach from it. | 76 | * to timeout on the lower level device, and eventually detach from it. |
@@ -87,7 +84,7 @@ void drbd_md_io_complete(struct bio *bio, int error) | |||
87 | * ASSERT(atomic_read(&device->md_io_in_use) == 1) there. | 84 | * ASSERT(atomic_read(&device->md_io_in_use) == 1) there. |
88 | */ | 85 | */ |
89 | drbd_md_put_buffer(device); | 86 | drbd_md_put_buffer(device); |
90 | md_io->done = 1; | 87 | device->md_io.done = 1; |
91 | wake_up(&device->misc_wait); | 88 | wake_up(&device->misc_wait); |
92 | bio_put(bio); | 89 | bio_put(bio); |
93 | if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */ | 90 | if (device->ldev) /* special case: drbd_md_read() during drbd_adm_attach() */ |