init_completion(&md_io.event);
md_io.error = 0;
- if ((rw & WRITE) && !test_bit(MD_NO_BARRIER, &mdev->flags))
- rw |= REQ_HARDBARRIER;
+ if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags))
+ rw |= REQ_FUA;
rw |= REQ_UNPLUG | REQ_SYNC;
- retry:
bio = bio_alloc(GFP_NOIO, 1);
bio->bi_bdev = bdev->md_bdev;
bio->bi_sector = sector;
wait_for_completion(&md_io.event);
ok = bio_flagged(bio, BIO_UPTODATE) && md_io.error == 0;
- /* check for unsupported barrier op.
- * would rather check on EOPNOTSUPP, but that is not reliable.
- * don't try again for ANY return value != 0 */
- if (unlikely((bio->bi_rw & REQ_HARDBARRIER) && !ok)) {
- /* Try again with no barrier */
- dev_warn(DEV, "Barriers not supported on meta data device - disabling\n");
- set_bit(MD_NO_BARRIER, &mdev->flags);
- rw &= ~REQ_HARDBARRIER;
- bio_put(bio);
- goto retry;
- }
out:
bio_put(bio);
return ok;
u32 xor_sum = 0;
if (!get_ldev(mdev)) {
- dev_err(DEV, "get_ldev() failed in w_al_write_transaction\n");
+ dev_err(DEV,
+ "disk is %s, cannot start al transaction (-%d +%d)\n",
+ drbd_disk_str(mdev->state.disk), evicted, new_enr);
complete(&((struct update_al_work *)w)->event);
return 1;
}
/* do we have to do a bitmap write, first?
* TODO reduce maximum latency:
* submit both bios, then wait for both,
- * instead of doing two synchronous sector writes. */
+ * instead of doing two synchronous sector writes.
+ * For now, we must not write the transaction,
+ * if we cannot write out the bitmap of the evicted extent. */
if (mdev->state.conn < C_CONNECTED && evicted != LC_FREE)
drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT);
- mutex_lock(&mdev->md_io_mutex); /* protects md_io_page, al_tr_cycle, ... */
+ /* The bitmap write may have failed, causing a state change. */
+ if (mdev->state.disk < D_INCONSISTENT) {
+ dev_err(DEV,
+ "disk is %s, cannot write al transaction (-%d +%d)\n",
+ drbd_disk_str(mdev->state.disk), evicted, new_enr);
+ complete(&((struct update_al_work *)w)->event);
+ put_ldev(mdev);
+ return 1;
+ }
+
+ mutex_lock(&mdev->md_io_mutex); /* protects md_io_buffer, al_tr_cycle, ... */
buffer = (struct al_transaction *)page_address(mdev->md_io_page);
buffer->magic = __constant_cpu_to_be32(DRBD_MAGIC);
unsigned int enr;
unsigned long add = 0;
char ppb[10];
- int i;
+ int i, tmp;
wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
enr = lc_element_by_index(mdev->act_log, i)->lc_number;
if (enr == LC_FREE)
continue;
- add += drbd_bm_ALe_set_all(mdev, enr);
+ tmp = drbd_bm_ALe_set_all(mdev, enr);
+ dynamic_dev_dbg(DEV, "AL: set %d bits in extent %u\n", tmp, enr);
+ add += tmp;
}
lc_unlock(mdev->act_log);
* ok, (capacity & 7) != 0 sometimes, but who cares...
* we count rs_{total,left} in bits, not sectors.
*/
- spin_lock_irqsave(&mdev->al_lock, flags);
count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
- if (count) {
- /* we need the lock for drbd_try_clear_on_disk_bm */
- if (jiffies - mdev->rs_mark_time > HZ*10) {
- /* should be rolling marks,
- * but we estimate only anyways. */
- if (mdev->rs_mark_left != drbd_bm_total_weight(mdev) &&
+ if (count && get_ldev(mdev)) {
+ unsigned long now = jiffies;
+ unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+ int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+ if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+ unsigned long tw = drbd_bm_total_weight(mdev);
+ if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
mdev->state.conn != C_PAUSED_SYNC_T &&
mdev->state.conn != C_PAUSED_SYNC_S) {
- mdev->rs_mark_time = jiffies;
- mdev->rs_mark_left = drbd_bm_total_weight(mdev);
+ mdev->rs_mark_time[next] = now;
+ mdev->rs_mark_left[next] = tw;
+ mdev->rs_last_mark = next;
}
}
- if (get_ldev(mdev)) {
- drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
- put_ldev(mdev);
- }
+ spin_lock_irqsave(&mdev->al_lock, flags);
+ drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+ spin_unlock_irqrestore(&mdev->al_lock, flags);
+
/* just wake_up unconditional now, various lc_chaged(),
* lc_put() in drbd_try_clear_on_disk_bm(). */
wake_up = 1;
+ put_ldev(mdev);
}
- spin_unlock_irqrestore(&mdev->al_lock, flags);
if (wake_up)
wake_up(&mdev->al_wait);
}
* @mdev: DRBD device.
* @sector: The sector number.
*
- * This functions sleeps on al_wait. Returns 1 on success, 0 if interrupted.
+ * This functions sleeps on al_wait. Returns 0 on success, -EINTR if interrupted.
*/
int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector)
{
sig = wait_event_interruptible(mdev->al_wait,
(bm_ext = _bme_get(mdev, enr)));
if (sig)
- return 0;
+ return -EINTR;
if (test_bit(BME_LOCKED, &bm_ext->flags))
- return 1;
+ return 0;
for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
sig = wait_event_interruptible(mdev->al_wait,
wake_up(&mdev->al_wait);
}
spin_unlock_irq(&mdev->al_lock);
- return 0;
+ return -EINTR;
}
}
-
set_bit(BME_LOCKED, &bm_ext->flags);
-
- return 1;
+ return 0;
}
/**