drivers/block/drbd/drbd_actlog.c

Source file repositories/reference/linux-study-clean/drivers/block/drbd/drbd_actlog.c

File Facts

System
Linux kernel
Corpus path
drivers/block/drbd/drbd_actlog.c
Extension
.c
Size
37198 bytes
Lines
1237
Domain
Driver Families
Bucket
drivers/block
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

else if (!get_ldev_if_state(device, D_ATTACHING)) {
		/* Corresponding put_ldev in drbd_md_endio() */
		drbd_err(device, "ASSERT FAILED: get_ldev_if_state() == 1 in _drbd_md_sync_page_io()\n");
		err = -ENODEV;
		goto out;
	}

	bio_get(bio); /* one bio_put() is in the completion handler */
	atomic_inc(&device->md_io.in_use); /* drbd_md_put_buffer() is in the completion handler */
	device->md_io.submit_jif = jiffies;
	if (drbd_insert_fault(device, (op == REQ_OP_WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
		bio_io_error(bio);
	else
		submit_bio(bio);
	wait_until_done_or_force_detached(device, bdev, &device->md_io.done);
	if (!bio->bi_status)
		err = device->md_io.error;

 out:
	bio_put(bio);
	return err;
}

int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bdev,
			 sector_t sector, enum req_op op)
{
	int err;
	D_ASSERT(device, atomic_read(&device->md_io.in_use) == 1);

	BUG_ON(!bdev->md_bdev);

	dynamic_drbd_dbg(device, "meta_data io: %s [%d]:%s(,%llus,%s) %pS\n",
	     current->comm, current->pid, __func__,
	     (unsigned long long)sector, (op == REQ_OP_WRITE) ? "WRITE" : "READ",
	     (void*)_RET_IP_ );

	if (sector < drbd_md_first_sector(bdev) ||
	    sector + 7 > drbd_md_last_sector(bdev))
		drbd_alert(device, "%s [%d]:%s(,%llus,%s) out of range md access!\n",
		     current->comm, current->pid, __func__,
		     (unsigned long long)sector,
		     (op == REQ_OP_WRITE) ? "WRITE" : "READ");

	err = _drbd_md_sync_page_io(device, bdev, sector, op);
	if (err) {
		drbd_err(device, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n",
		    (unsigned long long)sector,
		    (op == REQ_OP_WRITE) ? "WRITE" : "READ", err);
	}
	return err;
}

static struct bm_extent *find_active_resync_extent(struct drbd_device *device, unsigned int enr)
{
	struct lc_element *tmp;
	tmp = lc_find(device->resync, enr/AL_EXT_PER_BM_SECT);
	if (unlikely(tmp != NULL)) {
		struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
		if (test_bit(BME_NO_WRITES, &bm_ext->flags))
			return bm_ext;
	}
	return NULL;
}

static struct lc_element *_al_get(struct drbd_device *device, unsigned int enr, bool nonblock)
{
	struct lc_element *al_ext;
	struct bm_extent *bm_ext;
	int wake;

	spin_lock_irq(&device->al_lock);
	bm_ext = find_active_resync_extent(device, enr);
	if (bm_ext) {
		wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
		spin_unlock_irq(&device->al_lock);
		if (wake)
			wake_up(&device->al_wait);
		return NULL;
	}
	if (nonblock)
		al_ext = lc_try_get(device->act_log, enr);
	else
		al_ext = lc_get(device->act_log, enr);
	spin_unlock_irq(&device->al_lock);
	return al_ext;
}

bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i)
{
	/* for bios crossing activity log extent boundaries,

Annotation

Implementation Notes