aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2014-04-01 17:53:30 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2014-07-10 12:35:10 -0400
commite37d2438d8e5e4c1225cf94d45347fa207835447 (patch)
treebd1756066196e9922c476f75759f4846455c2c63 /drivers/block
parenta8ba0d606933c34c13ea971491a7e0dfa50208ef (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.c26
-rw-r--r--drivers/block/drbd/drbd_int.h9
-rw-r--r--drivers/block/drbd/drbd_main.c14
-rw-r--r--drivers/block/drbd/drbd_nl.c4
-rw-r--r--drivers/block/drbd/drbd_worker.c9
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
95void *drbd_md_get_buffer(struct drbd_device *device) 95void *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
106void drbd_md_put_buffer(struct drbd_device *device) 112void 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
544struct drbd_md_io { 544struct 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);
1336extern void suspend_other_sg(struct drbd_device *device); 1339extern void suspend_other_sg(struct drbd_device *device);
1337extern int drbd_resync_finished(struct drbd_device *device); 1340extern int drbd_resync_finished(struct drbd_device *device);
1338/* maybe rather drbd_main.c ? */ 1341/* maybe rather drbd_main.c ? */
1339extern void *drbd_md_get_buffer(struct drbd_device *device); 1342extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent);
1340extern void drbd_md_put_buffer(struct drbd_device *device); 1343extern void drbd_md_put_buffer(struct drbd_device *device);
1341extern int drbd_md_sync_page_io(struct drbd_device *device, 1344extern 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:
2845out_no_minor_idr: 2845out_no_minor_idr:
2846 drbd_bm_cleanup(device); 2846 drbd_bm_cleanup(device);
2847out_no_bitmap: 2847out_no_bitmap:
2848 __free_page(device->md_io_page); 2848 __free_page(device->md_io.page);
2849out_no_io_page: 2849out_no_io_page:
2850 put_disk(disk); 2850 put_disk(disk);
2851out_no_disk: 2851out_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 */
68void drbd_md_io_complete(struct bio *bio, int error) 68void 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() */