void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector) { unsigned int enr = (sector >> (AL_EXTENT_SHIFT-9)); struct lc_element *extent; unsigned long flags; spin_lock_irqsave(&mdev->al_lock, flags); extent = lc_find(mdev->act_log, enr); if (!extent) { spin_unlock_irqrestore(&mdev->al_lock, flags); dev_err(DEV, "al_complete_io() called on inactive extent %u\n", enr); return; } if (lc_put(mdev->act_log, extent) == 0) wake_up(&mdev->al_wait); spin_unlock_irqrestore(&mdev->al_lock, flags); }
/* ATTENTION. The AL's extents are 4MB each, while the extents in the * resync LRU-cache are 16MB each. * The caller of this function has to hold an get_ldev() reference. * * TODO will be obsoleted once we have a caching lru of the on disk bitmap */ STATIC void drbd_try_clear_on_disk_bm(struct drbd_conf *mdev, sector_t sector, int count, int success) { struct lc_element *e; struct update_odbm_work *udw; unsigned int enr; D_ASSERT(atomic_read(&mdev->local_cnt)); /* I simply assume that a sector/size pair never crosses * a 16 MB extent border. (Currently this is true...) */ enr = BM_SECT_TO_EXT(sector); e = lc_get(mdev->resync, enr); if (e) { struct bm_extent *ext = lc_entry(e, struct bm_extent, lce); if (ext->lce.lc_number == enr) { if (success) ext->rs_left -= count; else ext->rs_failed += count; if (ext->rs_left < ext->rs_failed) { dev_err(DEV, "BAD! sector=%llus enr=%u rs_left=%d " "rs_failed=%d count=%d\n", (unsigned long long)sector, ext->lce.lc_number, ext->rs_left, ext->rs_failed, count); dump_stack(); lc_put(mdev->resync, &ext->lce); drbd_force_state(mdev, NS(conn, C_DISCONNECTING)); return; } } else { /* Normally this element should be in the cache, * since drbd_rs_begin_io() pulled it already in. * * But maybe an application write finished, and we set * something outside the resync lru_cache in sync. */ int rs_left = drbd_bm_e_weight(mdev, enr); if (ext->flags != 0) { dev_warn(DEV, "changing resync lce: %d[%u;%02lx]" " -> %d[%u;00]\n", ext->lce.lc_number, ext->rs_left, ext->flags, enr, rs_left); ext->flags = 0; } if (ext->rs_failed) { dev_warn(DEV, "Kicking resync_lru element enr=%u " "out with rs_failed=%d\n", ext->lce.lc_number, ext->rs_failed); } ext->rs_left = rs_left; ext->rs_failed = success ? 0 : count; lc_changed(mdev->resync, &ext->lce); } lc_put(mdev->resync, &ext->lce); /* no race, we are within the al_lock! */ if (ext->rs_left == ext->rs_failed) { ext->rs_failed = 0; udw = kmalloc(sizeof(*udw), GFP_ATOMIC); if (udw) { udw->enr = ext->lce.lc_number; udw->w.cb = w_update_odbm; drbd_queue_work_front(&mdev->data.work, &udw->w); } else { dev_warn(DEV, "Could not kmalloc an udw\n"); } } } else {