static void atodb_endio(struct bio *bio, int error) { struct drbd_atodb_wait *wc = bio->bi_private; struct drbd_conf *mdev = wc->mdev; struct page *page; int uptodate = bio_flagged(bio, BIO_UPTODATE); /* strange behavior of some lower level drivers... * fail the request by clearing the uptodate flag, * but do not return any error?! */ if (!error && !uptodate) error = -EIO; drbd_chk_io_error(mdev, error, TRUE); if (error && wc->error == 0) wc->error = error; if (atomic_dec_and_test(&wc->count)) complete(&wc->io_done); page = bio->bi_io_vec[0].bv_page; put_page(page); bio_put(bio); mdev->bm_writ_cnt++; put_ldev(mdev); }
int w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused) { struct update_al_work *aw = container_of(w, struct update_al_work, w); struct lc_element *updated = aw->al_ext; const unsigned int new_enr = aw->enr; const unsigned int evicted = aw->old_enr; struct al_transaction *buffer; sector_t sector; int i, n, mx; unsigned int extent_nr; u32 xor_sum = 0; if (!get_ldev(mdev)) { 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. * 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_page(mdev, al_extent_to_bm_page(evicted)); /* 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); buffer->tr_number = cpu_to_be32(mdev->al_tr_number); n = lc_index_of(mdev->act_log, updated); buffer->updates[0].pos = cpu_to_be32(n); buffer->updates[0].extent = cpu_to_be32(new_enr); xor_sum ^= new_enr; mx = min_t(int, AL_EXTENTS_PT, mdev->act_log->nr_elements - mdev->al_tr_cycle); for (i = 0; i < mx; i++) { unsigned idx = mdev->al_tr_cycle + i; extent_nr = lc_element_by_index(mdev->act_log, idx)->lc_number; buffer->updates[i+1].pos = cpu_to_be32(idx); buffer->updates[i+1].extent = cpu_to_be32(extent_nr); xor_sum ^= extent_nr; } for (; i < AL_EXTENTS_PT; i++) { buffer->updates[i+1].pos = __constant_cpu_to_be32(-1); buffer->updates[i+1].extent = __constant_cpu_to_be32(LC_FREE); xor_sum ^= LC_FREE; } mdev->al_tr_cycle += AL_EXTENTS_PT; if (mdev->al_tr_cycle >= mdev->act_log->nr_elements) mdev->al_tr_cycle = 0; buffer->xor_sum = cpu_to_be32(xor_sum); sector = mdev->ldev->md.md_offset + mdev->ldev->md.al_offset + mdev->al_tr_pos; if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) drbd_chk_io_error(mdev, 1, true); if (++mdev->al_tr_pos > div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT)) mdev->al_tr_pos = 0; D_ASSERT(mdev->al_tr_pos < MD_AL_MAX_SIZE); mdev->al_tr_number++; mutex_unlock(&mdev->md_io_mutex); complete(&((struct update_al_work *)w)->event); put_ldev(mdev); return 1; }