⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm-exception-store.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	e->new_chunk = cpu_to_le64(de->new_chunk);}/* * Registers the exceptions that are present in the current area. * 'full' is filled in to indicate if the area has been * filled. */static int insert_exceptions(struct pstore *ps, int *full){	int r;	unsigned int i;	struct disk_exception de;	/* presume the area is full */	*full = 1;	for (i = 0; i < ps->exceptions_per_area; i++) {		read_exception(ps, i, &de);		/*		 * If the new_chunk is pointing at the start of		 * the COW device, where the first metadata area		 * is we know that we've hit the end of the		 * exceptions.  Therefore the area is not full.		 */		if (de.new_chunk == 0LL) {			ps->current_committed = i;			*full = 0;			break;		}		/*		 * Keep track of the start of the free chunks.		 */		if (ps->next_free <= de.new_chunk)			ps->next_free = de.new_chunk + 1;		/*		 * Otherwise we add the exception to the snapshot.		 */		r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);		if (r)			return r;	}	return 0;}static int read_exceptions(struct pstore *ps){	uint32_t area;	int r, full = 1;	/*	 * Keeping reading chunks and inserting exceptions until	 * we find a partially full area.	 */	for (area = 0; full; area++) {		r = area_io(ps, area, READ);		if (r)			return r;		r = insert_exceptions(ps, &full);		if (r)			return r;	}	return 0;}static struct pstore *get_info(struct exception_store *store){	return (struct pstore *) store->context;}static void persistent_fraction_full(struct exception_store *store,				     sector_t *numerator, sector_t *denominator){	*numerator = get_info(store)->next_free * store->snap->chunk_size;	*denominator = get_dev_size(store->snap->cow->bdev);}static void persistent_destroy(struct exception_store *store){	struct pstore *ps = get_info(store);	destroy_workqueue(ps->metadata_wq);	dm_io_client_destroy(ps->io_client);	vfree(ps->callbacks);	free_area(ps);	kfree(ps);}static int persistent_read_metadata(struct exception_store *store){	int r, new_snapshot;	struct pstore *ps = get_info(store);	/*	 * Read the snapshot header.	 */	r = read_header(ps, &new_snapshot);	if (r)		return r;	/*	 * Now we know correct chunk_size, complete the initialisation.	 */	ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /				  sizeof(struct disk_exception);	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,			sizeof(*ps->callbacks));	if (!ps->callbacks)		return -ENOMEM;	/*	 * Do we need to setup a new snapshot ?	 */	if (new_snapshot) {		r = write_header(ps);		if (r) {			DMWARN("write_header failed");			return r;		}		r = zero_area(ps, 0);		if (r) {			DMWARN("zero_area(0) failed");			return r;		}	} else {		/*		 * Sanity checks.		 */		if (ps->version != SNAPSHOT_DISK_VERSION) {			DMWARN("unable to handle snapshot disk version %d",			       ps->version);			return -EINVAL;		}		/*		 * Metadata are valid, but snapshot is invalidated		 */		if (!ps->valid)			return 1;		/*		 * Read the metadata.		 */		r = read_exceptions(ps);		if (r)			return r;	}	return 0;}static int persistent_prepare(struct exception_store *store,			      struct dm_snap_exception *e){	struct pstore *ps = get_info(store);	uint32_t stride;	sector_t size = get_dev_size(store->snap->cow->bdev);	/* Is there enough room ? */	if (size < ((ps->next_free + 1) * store->snap->chunk_size))		return -ENOSPC;	e->new_chunk = ps->next_free;	/*	 * Move onto the next free pending, making sure to take	 * into account the location of the metadata chunks.	 */	stride = (ps->exceptions_per_area + 1);	if ((++ps->next_free % stride) == 1)		ps->next_free++;	atomic_inc(&ps->pending_count);	return 0;}static void persistent_commit(struct exception_store *store,			      struct dm_snap_exception *e,			      void (*callback) (void *, int success),			      void *callback_context){	int r;	unsigned int i;	struct pstore *ps = get_info(store);	struct disk_exception de;	struct commit_callback *cb;	de.old_chunk = e->old_chunk;	de.new_chunk = e->new_chunk;	write_exception(ps, ps->current_committed++, &de);	/*	 * Add the callback to the back of the array.  This code	 * is the only place where the callback array is	 * manipulated, and we know that it will never be called	 * multiple times concurrently.	 */	cb = ps->callbacks + ps->callback_count++;	cb->callback = callback;	cb->context = callback_context;	/*	 * If there are no more exceptions in flight, or we have	 * filled this metadata area we commit the exceptions to	 * disk.	 */	if (atomic_dec_and_test(&ps->pending_count) ||	    (ps->current_committed == ps->exceptions_per_area)) {		r = area_io(ps, ps->current_area, WRITE);		if (r)			ps->valid = 0;		/*		 * Have we completely filled the current area ?		 */		if (ps->current_committed == ps->exceptions_per_area) {			ps->current_committed = 0;			r = zero_area(ps, ps->current_area + 1);			if (r)				ps->valid = 0;		}		for (i = 0; i < ps->callback_count; i++) {			cb = ps->callbacks + i;			cb->callback(cb->context, r == 0 ? 1 : 0);		}		ps->callback_count = 0;	}}static void persistent_drop(struct exception_store *store){	struct pstore *ps = get_info(store);	ps->valid = 0;	if (write_header(ps))		DMWARN("write header failed");}int dm_create_persistent(struct exception_store *store){	struct pstore *ps;	/* allocate the pstore */	ps = kmalloc(sizeof(*ps), GFP_KERNEL);	if (!ps)		return -ENOMEM;	ps->snap = store->snap;	ps->valid = 1;	ps->version = SNAPSHOT_DISK_VERSION;	ps->area = NULL;	ps->next_free = 2;	/* skipping the header and first area */	ps->current_committed = 0;	ps->callback_count = 0;	atomic_set(&ps->pending_count, 0);	ps->callbacks = NULL;	ps->metadata_wq = create_singlethread_workqueue("ksnaphd");	if (!ps->metadata_wq) {		kfree(ps);		DMERR("couldn't start header metadata update thread");		return -ENOMEM;	}	store->destroy = persistent_destroy;	store->read_metadata = persistent_read_metadata;	store->prepare_exception = persistent_prepare;	store->commit_exception = persistent_commit;	store->drop_snapshot = persistent_drop;	store->fraction_full = persistent_fraction_full;	store->context = ps;	return 0;}/*----------------------------------------------------------------- * Implementation of the store for non-persistent snapshots. *---------------------------------------------------------------*/struct transient_c {	sector_t next_free;};static void transient_destroy(struct exception_store *store){	kfree(store->context);}static int transient_read_metadata(struct exception_store *store){	return 0;}static int transient_prepare(struct exception_store *store,			     struct dm_snap_exception *e){	struct transient_c *tc = (struct transient_c *) store->context;	sector_t size = get_dev_size(store->snap->cow->bdev);	if (size < (tc->next_free + store->snap->chunk_size))		return -1;	e->new_chunk = sector_to_chunk(store->snap, tc->next_free);	tc->next_free += store->snap->chunk_size;	return 0;}static void transient_commit(struct exception_store *store,			     struct dm_snap_exception *e,			     void (*callback) (void *, int success),			     void *callback_context){	/* Just succeed */	callback(callback_context, 1);}static void transient_fraction_full(struct exception_store *store,				    sector_t *numerator, sector_t *denominator){	*numerator = ((struct transient_c *) store->context)->next_free;	*denominator = get_dev_size(store->snap->cow->bdev);}int dm_create_transient(struct exception_store *store){	struct transient_c *tc;	store->destroy = transient_destroy;	store->read_metadata = transient_read_metadata;	store->prepare_exception = transient_prepare;	store->commit_exception = transient_commit;	store->drop_snapshot = NULL;	store->fraction_full = transient_fraction_full;	tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);	if (!tc)		return -ENOMEM;	tc->next_free = 0;	store->context = tc;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -