Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-2.6-dm:
  dm kcopyd: fix callback race
  dm kcopyd: prepare for callback race fix
  dm: implement basic barrier support
  dm: remove dm_request loop
  dm: rework queueing and suspension
  dm: simplify dm_request loop
  dm: split DMF_BLOCK_IO flag into two
  dm: rearrange dm_wq_work
  dm: remove limited barrier support
  dm: add integrity support
  • Loading branch information
Linus Torvalds committed Apr 9, 2009
2 parents 97c18e2 + 340cd44 commit df55292
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 87 deletions.
21 changes: 21 additions & 0 deletions drivers/md/dm-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,19 @@ static int populate_table(struct dm_table *table,
return dm_table_complete(table);
}

static int table_prealloc_integrity(struct dm_table *t,
struct mapped_device *md)
{
struct list_head *devices = dm_table_get_devices(t);
struct dm_dev_internal *dd;

list_for_each_entry(dd, devices, list)
if (bdev_get_integrity(dd->dm_dev.bdev))
return blk_integrity_register(dm_disk(md), NULL);

return 0;
}

static int table_load(struct dm_ioctl *param, size_t param_size)
{
int r;
Expand All @@ -1068,6 +1081,14 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
goto out;
}

r = table_prealloc_integrity(t, md);
if (r) {
DMERR("%s: could not register integrity profile.",
dm_device_name(md));
dm_table_destroy(t);
goto out;
}

down_write(&_hash_lock);
hc = dm_get_mdptr(md);
if (!hc || hc->md != md) {
Expand Down
23 changes: 15 additions & 8 deletions drivers/md/dm-kcopyd.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ static int run_complete_job(struct kcopyd_job *job)
dm_kcopyd_notify_fn fn = job->fn;
struct dm_kcopyd_client *kc = job->kc;

kcopyd_put_pages(kc, job->pages);
if (job->pages)
kcopyd_put_pages(kc, job->pages);
mempool_free(job, kc->job_pool);
fn(read_err, write_err, context);

Expand Down Expand Up @@ -461,6 +462,7 @@ static void segment_complete(int read_err, unsigned long write_err,
sector_t progress = 0;
sector_t count = 0;
struct kcopyd_job *job = (struct kcopyd_job *) context;
struct dm_kcopyd_client *kc = job->kc;

mutex_lock(&job->lock);

Expand Down Expand Up @@ -490,7 +492,7 @@ static void segment_complete(int read_err, unsigned long write_err,

if (count) {
int i;
struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
struct kcopyd_job *sub_job = mempool_alloc(kc->job_pool,
GFP_NOIO);

*sub_job = *job;
Expand All @@ -509,13 +511,16 @@ static void segment_complete(int read_err, unsigned long write_err,
} else if (atomic_dec_and_test(&job->sub_jobs)) {

/*
* To avoid a race we must keep the job around
* until after the notify function has completed.
* Otherwise the client may try and stop the job
* after we've completed.
* Queue the completion callback to the kcopyd thread.
*
* Some callers assume that all the completions are called
* from a single thread and don't race with each other.
*
* We must not call the callback directly here because this
* code may not be executing in the thread.
*/
job->fn(read_err, write_err, job->context);
mempool_free(job, job->kc->job_pool);
push(&kc->complete_jobs, job);
wake(kc);
}
}

Expand All @@ -528,6 +533,8 @@ static void split_job(struct kcopyd_job *job)
{
int i;

atomic_inc(&job->kc->nr_jobs);

atomic_set(&job->sub_jobs, SPLIT_COUNT);
for (i = 0; i < SPLIT_COUNT; i++)
segment_complete(0, 0u, job);
Expand Down
1 change: 0 additions & 1 deletion drivers/md/dm-linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ static struct target_type linear_target = {
.status = linear_status,
.ioctl = linear_ioctl,
.merge = linear_merge,
.features = DM_TARGET_SUPPORTS_BARRIERS,
};

int __init dm_linear_init(void)
Expand Down
59 changes: 40 additions & 19 deletions drivers/md/dm-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ struct dm_table {
sector_t *highs;
struct dm_target *targets;

unsigned barriers_supported:1;

/*
* Indicates the rw permissions for the new logical
* device. This should be a combination of FMODE_READ
Expand Down Expand Up @@ -243,7 +241,6 @@ int dm_table_create(struct dm_table **result, fmode_t mode,

INIT_LIST_HEAD(&t->devices);
atomic_set(&t->holders, 0);
t->barriers_supported = 1;

if (!num_targets)
num_targets = KEYS_PER_NODE;
Expand Down Expand Up @@ -751,10 +748,6 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/* FIXME: the plan is to combine high here and then have
* the merge fn apply the target level restrictions. */
combine_restrictions_low(&t->limits, &tgt->limits);

if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
t->barriers_supported = 0;

return 0;

bad:
Expand Down Expand Up @@ -799,12 +792,6 @@ int dm_table_complete(struct dm_table *t)

check_for_valid_limits(&t->limits);

/*
* We only support barriers if there is exactly one underlying device.
*/
if (!list_is_singular(&t->devices))
t->barriers_supported = 0;

/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
Expand Down Expand Up @@ -879,6 +866,45 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}

/*
* Set the integrity profile for this device if all devices used have
* matching profiles.
*/
static void dm_table_set_integrity(struct dm_table *t)
{
struct list_head *devices = dm_table_get_devices(t);
struct dm_dev_internal *prev = NULL, *dd = NULL;

if (!blk_get_integrity(dm_disk(t->md)))
return;

list_for_each_entry(dd, devices, list) {
if (prev &&
blk_integrity_compare(prev->dm_dev.bdev->bd_disk,
dd->dm_dev.bdev->bd_disk) < 0) {
DMWARN("%s: integrity not set: %s and %s mismatch",
dm_device_name(t->md),
prev->dm_dev.bdev->bd_disk->disk_name,
dd->dm_dev.bdev->bd_disk->disk_name);
goto no_integrity;
}
prev = dd;
}

if (!prev || !bdev_get_integrity(prev->dm_dev.bdev))
goto no_integrity;

blk_integrity_register(dm_disk(t->md),
bdev_get_integrity(prev->dm_dev.bdev));

return;

no_integrity:
blk_integrity_register(dm_disk(t->md), NULL);

return;
}

void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
{
/*
Expand All @@ -899,6 +925,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
else
queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);

dm_table_set_integrity(t);
}

unsigned int dm_table_get_num_targets(struct dm_table *t)
Expand Down Expand Up @@ -1019,12 +1046,6 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
return t->md;
}

int dm_table_barrier_ok(struct dm_table *t)
{
return t->barriers_supported;
}
EXPORT_SYMBOL(dm_table_barrier_ok);

EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
Expand Down
Loading

0 comments on commit df55292

Please sign in to comment.