Skip to content

Commit a70f35a

Browse files
committed
Merge branch 'for-3.5/drivers' of git://git.kernel.dk/linux-block
Pull block driver updates from Jens Axboe: "Here are the driver related changes for 3.5. It contains: - The floppy changes from Jiri. Jiri is now also marked as the maintainer of floppy.c, I shall be publically branding his forehead with red hot iron at the next opportune moment. - A batch of drbd updates and fixes from the linbit crew, as well as fixes from others. - Two small fixes for xen-blkfront courtesy of Jan." * 'for-3.5/drivers' of git://git.kernel.dk/linux-block: (70 commits) floppy: take over maintainership floppy: remove floppy-specific O_EXCL handling floppy: convert to delayed work and single-thread wq xen-blkfront: module exit handling adjustments xen-blkfront: properly name all devices drbd: grammar fix in log message drbd: check MODULE for THIS_MODULE drbd: Restore the request restart logic drbd: introduce a bio_set to allocate housekeeping bios from drbd: remove unused define drbd: bm_page_async_io: properly initialize page->private drbd: use the newly introduced page pool for bitmap IO drbd: add page pool to be used for meta data IO drbd: allow bitmap to change during writeout from resync_finished drbd: fix race between drbdadm invalidate/verify and finishing resync drbd: fix resend/resubmit of frozen IO drbd: Ensure that data_size is not 0 before using data_size-1 as index drbd: Delay/reject other state changes while establishing a connection drbd: move put_ldev from __req_mod() to the endio callback drbd: fix WRITE_ACKED_BY_PEER_AND_SIS to not set RQ_NET_DONE ...
2 parents 0d16751 + 4fd1ffa commit a70f35a

File tree

16 files changed

+862
-391
lines changed

16 files changed

+862
-391
lines changed

MAINTAINERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,6 +2818,12 @@ F: Documentation/firmware_class/
28182818
F: drivers/base/firmware*.c
28192819
F: include/linux/firmware.h
28202820

2821+
FLOPPY DRIVER
2822+
M: Jiri Kosina <jkosina@suse.cz>
2823+
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy.git
2824+
S: Odd fixes
2825+
F: drivers/block/floppy.c
2826+
28212827
FPU EMULATOR
28222828
M: Bill Metzenthen <billm@melbpc.org.au>
28232829
W: http://floatingpoint.sourceforge.net/emulator/index.html

drivers/block/drbd/drbd_actlog.c

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -65,39 +65,80 @@ struct drbd_atodb_wait {
6565

6666
int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int);
6767

68+
void *drbd_md_get_buffer(struct drbd_conf *mdev)
69+
{
70+
int r;
71+
72+
wait_event(mdev->misc_wait,
73+
(r = atomic_cmpxchg(&mdev->md_io_in_use, 0, 1)) == 0 ||
74+
mdev->state.disk <= D_FAILED);
75+
76+
return r ? NULL : page_address(mdev->md_io_page);
77+
}
78+
79+
void drbd_md_put_buffer(struct drbd_conf *mdev)
80+
{
81+
if (atomic_dec_and_test(&mdev->md_io_in_use))
82+
wake_up(&mdev->misc_wait);
83+
}
84+
85+
static bool md_io_allowed(struct drbd_conf *mdev)
86+
{
87+
enum drbd_disk_state ds = mdev->state.disk;
88+
return ds >= D_NEGOTIATING || ds == D_ATTACHING;
89+
}
90+
91+
void wait_until_done_or_disk_failure(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
92+
unsigned int *done)
93+
{
94+
long dt = bdev->dc.disk_timeout * HZ / 10;
95+
if (dt == 0)
96+
dt = MAX_SCHEDULE_TIMEOUT;
97+
98+
dt = wait_event_timeout(mdev->misc_wait, *done || !md_io_allowed(mdev), dt);
99+
if (dt == 0)
100+
dev_err(DEV, "meta-data IO operation timed out\n");
101+
}
102+
68103
static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
69104
struct drbd_backing_dev *bdev,
70105
struct page *page, sector_t sector,
71106
int rw, int size)
72107
{
73108
struct bio *bio;
74-
struct drbd_md_io md_io;
75109
int ok;
76110

77-
md_io.mdev = mdev;
78-
init_completion(&md_io.event);
79-
md_io.error = 0;
111+
mdev->md_io.done = 0;
112+
mdev->md_io.error = -ENODEV;
80113

81114
if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags))
82115
rw |= REQ_FUA | REQ_FLUSH;
83116
rw |= REQ_SYNC;
84117

85-
bio = bio_alloc(GFP_NOIO, 1);
118+
bio = bio_alloc_drbd(GFP_NOIO);
86119
bio->bi_bdev = bdev->md_bdev;
87120
bio->bi_sector = sector;
88121
ok = (bio_add_page(bio, page, size, 0) == size);
89122
if (!ok)
90123
goto out;
91-
bio->bi_private = &md_io;
124+
bio->bi_private = &mdev->md_io;
92125
bio->bi_end_io = drbd_md_io_complete;
93126
bio->bi_rw = rw;
94127

128+
if (!get_ldev_if_state(mdev, D_ATTACHING)) { /* Corresponding put_ldev in drbd_md_io_complete() */
129+
dev_err(DEV, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
130+
ok = 0;
131+
goto out;
132+
}
133+
134+
bio_get(bio); /* one bio_put() is in the completion handler */
135+
atomic_inc(&mdev->md_io_in_use); /* drbd_md_put_buffer() is in the completion handler */
95136
if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
96137
bio_endio(bio, -EIO);
97138
else
98139
submit_bio(rw, bio);
99-
wait_for_completion(&md_io.event);
100-
ok = bio_flagged(bio, BIO_UPTODATE) && md_io.error == 0;
140+
wait_until_done_or_disk_failure(mdev, bdev, &mdev->md_io.done);
141+
ok = bio_flagged(bio, BIO_UPTODATE) && mdev->md_io.error == 0;
101142

102143
out:
103144
bio_put(bio);
@@ -111,7 +152,7 @@ int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev,
111152
int offset = 0;
112153
struct page *iop = mdev->md_io_page;
113154

114-
D_ASSERT(mutex_is_locked(&mdev->md_io_mutex));
155+
D_ASSERT(atomic_read(&mdev->md_io_in_use) == 1);
115156

116157
BUG_ON(!bdev->md_bdev);
117158

@@ -328,8 +369,13 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
328369
return 1;
329370
}
330371

331-
mutex_lock(&mdev->md_io_mutex); /* protects md_io_buffer, al_tr_cycle, ... */
332-
buffer = (struct al_transaction *)page_address(mdev->md_io_page);
372+
buffer = drbd_md_get_buffer(mdev); /* protects md_io_buffer, al_tr_cycle, ... */
373+
if (!buffer) {
374+
dev_err(DEV, "disk failed while waiting for md_io buffer\n");
375+
complete(&((struct update_al_work *)w)->event);
376+
put_ldev(mdev);
377+
return 1;
378+
}
333379

334380
buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC);
335381
buffer->tr_number = cpu_to_be32(mdev->al_tr_number);
@@ -374,7 +420,7 @@ w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
374420
D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE);
375421
mdev->al_tr_number++;
376422

377-
mutex_unlock(&mdev->md_io_mutex);
423+
drbd_md_put_buffer(mdev);
378424

379425
complete(&((struct update_al_work *)w)->event);
380426
put_ldev(mdev);
@@ -443,16 +489,17 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
443489
/* lock out all other meta data io for now,
444490
* and make sure the page is mapped.
445491
*/
446-
mutex_lock(&mdev->md_io_mutex);
447-
buffer = page_address(mdev->md_io_page);
492+
buffer = drbd_md_get_buffer(mdev);
493+
if (!buffer)
494+
return 0;
448495

449496
/* Find the valid transaction in the log */
450497
for (i = 0; i <= mx; i++) {
451498
rv = drbd_al_read_tr(mdev, bdev, buffer, i);
452499
if (rv == 0)
453500
continue;
454501
if (rv == -1) {
455-
mutex_unlock(&mdev->md_io_mutex);
502+
drbd_md_put_buffer(mdev);
456503
return 0;
457504
}
458505
cnr = be32_to_cpu(buffer->tr_number);
@@ -478,7 +525,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
478525

479526
if (!found_valid) {
480527
dev_warn(DEV, "No usable activity log found.\n");
481-
mutex_unlock(&mdev->md_io_mutex);
528+
drbd_md_put_buffer(mdev);
482529
return 1;
483530
}
484531

@@ -493,7 +540,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
493540
rv = drbd_al_read_tr(mdev, bdev, buffer, i);
494541
ERR_IF(rv == 0) goto cancel;
495542
if (rv == -1) {
496-
mutex_unlock(&mdev->md_io_mutex);
543+
drbd_md_put_buffer(mdev);
497544
return 0;
498545
}
499546

@@ -534,7 +581,7 @@ int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
534581
mdev->al_tr_pos = 0;
535582

536583
/* ok, we are done with it */
537-
mutex_unlock(&mdev->md_io_mutex);
584+
drbd_md_put_buffer(mdev);
538585

539586
dev_info(DEV, "Found %d transactions (%d active extents) in activity log.\n",
540587
transactions, active_extents);
@@ -671,16 +718,20 @@ static void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector,
671718
else
672719
ext->rs_failed += count;
673720
if (ext->rs_left < ext->rs_failed) {
674-
dev_err(DEV, "BAD! sector=%llus enr=%u rs_left=%d "
675-
"rs_failed=%d count=%d\n",
721+
dev_warn(DEV, "BAD! sector=%llus enr=%u rs_left=%d "
722+
"rs_failed=%d count=%d cstate=%s\n",
676723
(unsigned long long)sector,
677724
ext->lce.lc_number, ext->rs_left,
678-
ext->rs_failed, count);
679-
dump_stack();
680-
681-
lc_put(mdev->resync, &ext->lce);
682-
drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
683-
return;
725+
ext->rs_failed, count,
726+
drbd_conn_str(mdev->state.conn));
727+
728+
/* We don't expect to be able to clear more bits
729+
* than have been set when we originally counted
730+
* the set bits to cache that value in ext->rs_left.
731+
* Whatever the reason (disconnect during resync,
732+
* delayed local completion of an application write),
733+
* try to fix it up by recounting here. */
734+
ext->rs_left = drbd_bm_e_weight(mdev, enr);
684735
}
685736
} else {
686737
/* Normally this element should be in the cache,
@@ -1192,6 +1243,7 @@ int drbd_rs_del_all(struct drbd_conf *mdev)
11921243
put_ldev(mdev);
11931244
}
11941245
spin_unlock_irq(&mdev->al_lock);
1246+
wake_up(&mdev->al_wait);
11951247

11961248
return 0;
11971249
}

0 commit comments

Comments
 (0)