~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/md/dm-table.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
        struct dm_target *targets;
56
56
 
57
57
        unsigned discards_supported:1;
 
58
        unsigned integrity_supported:1;
58
59
 
59
60
        /*
60
61
         * Indicates the rw permissions for the new logical
361
362
static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
362
363
                                  sector_t start, sector_t len, void *data)
363
364
{
 
365
        struct request_queue *q;
364
366
        struct queue_limits *limits = data;
365
367
        struct block_device *bdev = dev->bdev;
366
368
        sector_t dev_size =
369
371
                limits->logical_block_size >> SECTOR_SHIFT;
370
372
        char b[BDEVNAME_SIZE];
371
373
 
 
374
        /*
 
375
         * Some devices exist without request functions,
 
376
         * such as loop devices not yet bound to backing files.
 
377
         * Forbid the use of such devices.
 
378
         */
 
379
        q = bdev_get_queue(bdev);
 
380
        if (!q || !q->make_request_fn) {
 
381
                DMWARN("%s: %s is not yet initialised: "
 
382
                       "start=%llu, len=%llu, dev_size=%llu",
 
383
                       dm_device_name(ti->table->md), bdevname(bdev, b),
 
384
                       (unsigned long long)start,
 
385
                       (unsigned long long)len,
 
386
                       (unsigned long long)dev_size);
 
387
                return 1;
 
388
        }
 
389
 
372
390
        if (!dev_size)
373
391
                return 0;
374
392
 
859
877
                return -EINVAL;
860
878
        }
861
879
 
862
 
        t->mempools = dm_alloc_md_mempools(type);
 
880
        t->mempools = dm_alloc_md_mempools(type, t->integrity_supported);
863
881
        if (!t->mempools)
864
882
                return -ENOMEM;
865
883
 
926
944
}
927
945
 
928
946
/*
 
947
 * Get a disk whose integrity profile reflects the table's profile.
 
948
 * If %match_all is true, all devices' profiles must match.
 
949
 * If %match_all is false, all devices must at least have an
 
950
 * allocated integrity profile; but uninitialized is ok.
 
951
 * Returns NULL if integrity support was inconsistent or unavailable.
 
952
 */
 
953
static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
 
954
                                                    bool match_all)
 
955
{
 
956
        struct list_head *devices = dm_table_get_devices(t);
 
957
        struct dm_dev_internal *dd = NULL;
 
958
        struct gendisk *prev_disk = NULL, *template_disk = NULL;
 
959
 
 
960
        list_for_each_entry(dd, devices, list) {
 
961
                template_disk = dd->dm_dev.bdev->bd_disk;
 
962
                if (!blk_get_integrity(template_disk))
 
963
                        goto no_integrity;
 
964
                if (!match_all && !blk_integrity_is_initialized(template_disk))
 
965
                        continue; /* skip uninitialized profiles */
 
966
                else if (prev_disk &&
 
967
                         blk_integrity_compare(prev_disk, template_disk) < 0)
 
968
                        goto no_integrity;
 
969
                prev_disk = template_disk;
 
970
        }
 
971
 
 
972
        return template_disk;
 
973
 
 
974
no_integrity:
 
975
        if (prev_disk)
 
976
                DMWARN("%s: integrity not set: %s and %s profile mismatch",
 
977
                       dm_device_name(t->md),
 
978
                       prev_disk->disk_name,
 
979
                       template_disk->disk_name);
 
980
        return NULL;
 
981
}
 
982
 
 
983
/*
929
984
 * Register the mapped device for blk_integrity support if
930
 
 * the underlying devices support it.
 
985
 * the underlying devices have an integrity profile.  But all devices
 
986
 * may not have matching profiles (checking all devices isn't reliable
 
987
 * during table load because this table may use other DM device(s) which
 
988
 * must be resumed before they will have an initialized integity profile).
 
989
 * Stacked DM devices force a 2 stage integrity profile validation:
 
990
 * 1 - during load, validate all initialized integrity profiles match
 
991
 * 2 - during resume, validate all integrity profiles match
931
992
 */
932
993
static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
933
994
{
934
 
        struct list_head *devices = dm_table_get_devices(t);
935
 
        struct dm_dev_internal *dd;
936
 
 
937
 
        list_for_each_entry(dd, devices, list)
938
 
                if (bdev_get_integrity(dd->dm_dev.bdev))
939
 
                        return blk_integrity_register(dm_disk(md), NULL);
940
 
 
 
995
        struct gendisk *template_disk = NULL;
 
996
 
 
997
        template_disk = dm_table_get_integrity_disk(t, false);
 
998
        if (!template_disk)
 
999
                return 0;
 
1000
 
 
1001
        if (!blk_integrity_is_initialized(dm_disk(md))) {
 
1002
                t->integrity_supported = 1;
 
1003
                return blk_integrity_register(dm_disk(md), NULL);
 
1004
        }
 
1005
 
 
1006
        /*
 
1007
         * If DM device already has an initalized integrity
 
1008
         * profile the new profile should not conflict.
 
1009
         */
 
1010
        if (blk_integrity_is_initialized(template_disk) &&
 
1011
            blk_integrity_compare(dm_disk(md), template_disk) < 0) {
 
1012
                DMWARN("%s: conflict with existing integrity profile: "
 
1013
                       "%s profile mismatch",
 
1014
                       dm_device_name(t->md),
 
1015
                       template_disk->disk_name);
 
1016
                return 1;
 
1017
        }
 
1018
 
 
1019
        /* Preserve existing initialized integrity profile */
 
1020
        t->integrity_supported = 1;
941
1021
        return 0;
942
1022
}
943
1023
 
1091
1171
 
1092
1172
/*
1093
1173
 * Set the integrity profile for this device if all devices used have
1094
 
 * matching profiles.
 
1174
 * matching profiles.  We're quite deep in the resume path but still
 
1175
 * don't know if all devices (particularly DM devices this device
 
1176
 * may be stacked on) have matching profiles.  Even if the profiles
 
1177
 * don't match we have no way to fail (to resume) at this point.
1095
1178
 */
1096
1179
static void dm_table_set_integrity(struct dm_table *t)
1097
1180
{
1098
 
        struct list_head *devices = dm_table_get_devices(t);
1099
 
        struct dm_dev_internal *prev = NULL, *dd = NULL;
 
1181
        struct gendisk *template_disk = NULL;
1100
1182
 
1101
1183
        if (!blk_get_integrity(dm_disk(t->md)))
1102
1184
                return;
1103
1185
 
1104
 
        list_for_each_entry(dd, devices, list) {
1105
 
                if (prev &&
1106
 
                    blk_integrity_compare(prev->dm_dev.bdev->bd_disk,
1107
 
                                          dd->dm_dev.bdev->bd_disk) < 0) {
1108
 
                        DMWARN("%s: integrity not set: %s and %s mismatch",
1109
 
                               dm_device_name(t->md),
1110
 
                               prev->dm_dev.bdev->bd_disk->disk_name,
1111
 
                               dd->dm_dev.bdev->bd_disk->disk_name);
1112
 
                        goto no_integrity;
1113
 
                }
1114
 
                prev = dd;
 
1186
        template_disk = dm_table_get_integrity_disk(t, true);
 
1187
        if (!template_disk &&
 
1188
            blk_integrity_is_initialized(dm_disk(t->md))) {
 
1189
                DMWARN("%s: device no longer has a valid integrity profile",
 
1190
                       dm_device_name(t->md));
 
1191
                return;
1115
1192
        }
1116
 
 
1117
 
        if (!prev || !bdev_get_integrity(prev->dm_dev.bdev))
1118
 
                goto no_integrity;
1119
 
 
1120
1193
        blk_integrity_register(dm_disk(t->md),
1121
 
                               bdev_get_integrity(prev->dm_dev.bdev));
1122
 
 
1123
 
        return;
1124
 
 
1125
 
no_integrity:
1126
 
        blk_integrity_register(dm_disk(t->md), NULL);
1127
 
 
1128
 
        return;
 
1194
                               blk_get_integrity(template_disk));
1129
1195
}
1130
1196
 
1131
1197
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1275
1341
        return 0;
1276
1342
}
1277
1343
 
1278
 
void dm_table_unplug_all(struct dm_table *t)
1279
 
{
1280
 
        struct dm_dev_internal *dd;
1281
 
        struct list_head *devices = dm_table_get_devices(t);
1282
 
        struct dm_target_callbacks *cb;
1283
 
 
1284
 
        list_for_each_entry(dd, devices, list) {
1285
 
                struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
1286
 
                char b[BDEVNAME_SIZE];
1287
 
 
1288
 
                if (likely(q))
1289
 
                        blk_unplug(q);
1290
 
                else
1291
 
                        DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s",
1292
 
                                     dm_device_name(t->md),
1293
 
                                     bdevname(dd->dm_dev.bdev, b));
1294
 
        }
1295
 
 
1296
 
        list_for_each_entry(cb, &t->target_callbacks, list)
1297
 
                if (cb->unplug_fn)
1298
 
                        cb->unplug_fn(cb);
1299
 
}
1300
 
 
1301
1344
struct mapped_device *dm_table_get_md(struct dm_table *t)
1302
1345
{
1303
1346
        return t->md;
1320
1363
                return 0;
1321
1364
 
1322
1365
        /*
1323
 
         * Ensure that at least one underlying device supports discards.
 
1366
         * Unless any target used by the table set discards_supported,
 
1367
         * require at least one underlying device to support discards.
1324
1368
         * t->devices includes internal dm devices such as mirror logs
1325
1369
         * so we need to use iterate_devices here, which targets
1326
1370
         * supporting discard must provide.
1328
1372
        while (i < dm_table_get_num_targets(t)) {
1329
1373
                ti = dm_table_get_target(t, i++);
1330
1374
 
 
1375
                if (ti->discards_supported)
 
1376
                        return 1;
 
1377
 
1331
1378
                if (ti->type->iterate_devices &&
1332
1379
                    ti->type->iterate_devices(ti, device_discard_capable, NULL))
1333
1380
                        return 1;
1345
1392
EXPORT_SYMBOL(dm_table_get_md);
1346
1393
EXPORT_SYMBOL(dm_table_put);
1347
1394
EXPORT_SYMBOL(dm_table_get);
1348
 
EXPORT_SYMBOL(dm_table_unplug_all);