STATIC int w_update_odbm(struct drbd_conf *mdev, struct drbd_work *w, int unused) { struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w); if (!get_ldev(mdev)) { if (DRBD_ratelimit(5*HZ, 5)) dev_warn(DEV, "Can not update on disk bitmap, local IO disabled.\n"); kfree(udw); return 1; } drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr)); put_ldev(mdev); kfree(udw); if (drbd_bm_total_weight(mdev) <= mdev->rs_failed) { switch (mdev->state.conn) { case C_SYNC_SOURCE: case C_SYNC_TARGET: case C_PAUSED_SYNC_S: case C_PAUSED_SYNC_T: drbd_resync_finished(mdev); default: /* nothing to do */ break; } } drbd_bcast_sync_progress(mdev); return 1; }
/* rw is bio_data_dir(), only READ or WRITE */ static void _req_is_done(struct drbd_conf *mdev, struct drbd_request *req, const int rw) { const unsigned long s = req->rq_state; /* remove it from the transfer log. * well, only if it had been there in the first * place... if it had not (local only or conflicting * and never sent), it should still be "empty" as * initialized in drbd_req_new(), so we can list_del() it * here unconditionally */ list_del(&req->tl_requests); /* if it was a write, we may have to set the corresponding * bit(s) out-of-sync first. If it had a local part, we need to * release the reference to the activity log. */ if (rw == WRITE) { /* Set out-of-sync unless both OK flags are set * (local only or remote failed). * Other places where we set out-of-sync: * READ with local io-error */ if (!(s & RQ_NET_OK) || !(s & RQ_LOCAL_OK)) drbd_set_out_of_sync(mdev, req->sector, req->size); if ((s & RQ_NET_OK) && (s & RQ_LOCAL_OK) && (s & RQ_NET_SIS)) drbd_set_in_sync(mdev, req->sector, req->size); /* one might be tempted to move the drbd_al_complete_io * to the local io completion callback drbd_endio_pri. * but, if this was a mirror write, we may only * drbd_al_complete_io after this is RQ_NET_DONE, * otherwise the extent could be dropped from the al * before it has actually been written on the peer. * if we crash before our peer knows about the request, * but after the extent has been dropped from the al, * we would forget to resync the corresponding extent. */ if (s & RQ_LOCAL_MASK) { if (get_ldev_if_state(mdev, D_FAILED)) { if (s & RQ_IN_ACT_LOG) drbd_al_complete_io(mdev, req->sector); put_ldev(mdev); } else if (DRBD_ratelimit(5*HZ, 3)) { dev_warn(DEV, "Should have called drbd_al_complete_io(, %llu), " "but my Disk seems to have failed :(\n", (unsigned long long) req->sector); } } } drbd_req_free(req); }
int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, sector_t sector, int rw) { int logical_block_size, mask, ok; int offset = 0; struct page *iop = mdev->md_io_page; D_ASSERT(mutex_is_locked(&mdev->md_io_mutex)); if (!bdev->md_bdev) { if (DRBD_ratelimit(5*HZ, 5)) { dev_err(DEV, "bdev->md_bdev==NULL\n"); dump_stack(); } return 0; } logical_block_size = bdev_logical_block_size(bdev->md_bdev); if (logical_block_size == 0) logical_block_size = MD_SECTOR_SIZE; /* in case logical_block_size != 512 [ s390 only? ] */ if (logical_block_size != MD_SECTOR_SIZE) { mask = (logical_block_size / MD_SECTOR_SIZE) - 1; D_ASSERT(mask == 1 || mask == 3 || mask == 7); D_ASSERT(logical_block_size == (mask+1) * MD_SECTOR_SIZE); offset = sector & mask; sector = sector & ~mask; iop = mdev->md_io_tmpp; if (rw & WRITE) { /* these are GFP_KERNEL pages, pre-allocated * on device initialization */ void *p = page_address(mdev->md_io_page); void *hp = page_address(mdev->md_io_tmpp); ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, READ, logical_block_size); if (unlikely(!ok)) { dev_err(DEV, "drbd_md_sync_page_io(,%llus," "READ [logical_block_size!=512]) failed!\n", (unsigned long long)sector); return 0; } memcpy(hp + offset*MD_SECTOR_SIZE, p, MD_SECTOR_SIZE); } } #if DUMP_MD >= 3 dev_info(DEV, "%s [%d]:%s(,%llus,%s)\n", current->comm, current->pid, __func__, (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); #endif if (sector < drbd_md_first_sector(bdev) || sector > drbd_md_last_sector(bdev)) dev_alert(DEV, "%s [%d]:%s(,%llus,%s) out of range md access!\n", current->comm, current->pid, __func__, (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, logical_block_size); if (unlikely(!ok)) { dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed!\n", (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); return 0; } if (logical_block_size != MD_SECTOR_SIZE && !(rw & WRITE)) { void *p = page_address(mdev->md_io_page); void *hp = page_address(mdev->md_io_tmpp); memcpy(p, hp + offset*MD_SECTOR_SIZE, MD_SECTOR_SIZE); } return ok; }