aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-table.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-02 20:02:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-02 20:02:37 -0400
commit43672a0784707d795556b1f93925da8b8e797d03 (patch)
tree5c92aabd211281300f89fc2e69e9ee7e58bcc449 /drivers/md/dm-table.c
parent2380078cdb7e6d520e33dcf834e0be979d542e48 (diff)
parent2e727c3ca1beff05f27b6207a795790f222bf8d8 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/linux-dm
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/linux-dm: dm: raid fix device status indicator when array initializing dm log userspace: add log device dependency dm log userspace: fix comment hyphens dm: add thin provisioning target dm: add persistent data library dm: add bufio dm: export dm get md dm table: add immutable feature dm table: add always writeable feature dm table: add singleton feature dm kcopyd: add dm_kcopyd_zero to zero an area dm: remove superfluous smp_mb dm: use local printk ratelimit dm table: propagate non rotational flag
Diffstat (limited to 'drivers/md/dm-table.c')
-rw-r--r--drivers/md/dm-table.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index bc04518e9d8..8e913213014 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -54,7 +54,9 @@ struct dm_table {
54 sector_t *highs; 54 sector_t *highs;
55 struct dm_target *targets; 55 struct dm_target *targets;
56 56
57 struct target_type *immutable_target_type;
57 unsigned integrity_supported:1; 58 unsigned integrity_supported:1;
59 unsigned singleton:1;
58 60
59 /* 61 /*
60 * Indicates the rw permissions for the new logical 62 * Indicates the rw permissions for the new logical
@@ -740,6 +742,12 @@ int dm_table_add_target(struct dm_table *t, const char *type,
740 char **argv; 742 char **argv;
741 struct dm_target *tgt; 743 struct dm_target *tgt;
742 744
745 if (t->singleton) {
746 DMERR("%s: target type %s must appear alone in table",
747 dm_device_name(t->md), t->targets->type->name);
748 return -EINVAL;
749 }
750
743 if ((r = check_space(t))) 751 if ((r = check_space(t)))
744 return r; 752 return r;
745 753
@@ -758,6 +766,36 @@ int dm_table_add_target(struct dm_table *t, const char *type,
758 return -EINVAL; 766 return -EINVAL;
759 } 767 }
760 768
769 if (dm_target_needs_singleton(tgt->type)) {
770 if (t->num_targets) {
771 DMERR("%s: target type %s must appear alone in table",
772 dm_device_name(t->md), type);
773 return -EINVAL;
774 }
775 t->singleton = 1;
776 }
777
778 if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
779 DMERR("%s: target type %s may not be included in read-only tables",
780 dm_device_name(t->md), type);
781 return -EINVAL;
782 }
783
784 if (t->immutable_target_type) {
785 if (t->immutable_target_type != tgt->type) {
786 DMERR("%s: immutable target type %s cannot be mixed with other target types",
787 dm_device_name(t->md), t->immutable_target_type->name);
788 return -EINVAL;
789 }
790 } else if (dm_target_is_immutable(tgt->type)) {
791 if (t->num_targets) {
792 DMERR("%s: immutable target type %s cannot be mixed with other target types",
793 dm_device_name(t->md), tgt->type->name);
794 return -EINVAL;
795 }
796 t->immutable_target_type = tgt->type;
797 }
798
761 tgt->table = t; 799 tgt->table = t;
762 tgt->begin = start; 800 tgt->begin = start;
763 tgt->len = len; 801 tgt->len = len;
@@ -915,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t)
915 return t->type; 953 return t->type;
916} 954}
917 955
956struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
957{
958 return t->immutable_target_type;
959}
960
918bool dm_table_request_based(struct dm_table *t) 961bool dm_table_request_based(struct dm_table *t)
919{ 962{
920 return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED; 963 return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1299,6 +1342,31 @@ static bool dm_table_discard_zeroes_data(struct dm_table *t)
1299 return 1; 1342 return 1;
1300} 1343}
1301 1344
1345static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
1346 sector_t start, sector_t len, void *data)
1347{
1348 struct request_queue *q = bdev_get_queue(dev->bdev);
1349
1350 return q && blk_queue_nonrot(q);
1351}
1352
1353static bool dm_table_is_nonrot(struct dm_table *t)
1354{
1355 struct dm_target *ti;
1356 unsigned i = 0;
1357
1358 /* Ensure that all underlying device are non-rotational. */
1359 while (i < dm_table_get_num_targets(t)) {
1360 ti = dm_table_get_target(t, i++);
1361
1362 if (!ti->type->iterate_devices ||
1363 !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
1364 return 0;
1365 }
1366
1367 return 1;
1368}
1369
1302void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, 1370void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1303 struct queue_limits *limits) 1371 struct queue_limits *limits)
1304{ 1372{
@@ -1324,6 +1392,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
1324 if (!dm_table_discard_zeroes_data(t)) 1392 if (!dm_table_discard_zeroes_data(t))
1325 q->limits.discard_zeroes_data = 0; 1393 q->limits.discard_zeroes_data = 0;
1326 1394
1395 if (dm_table_is_nonrot(t))
1396 queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
1397 else
1398 queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
1399
1327 dm_table_set_integrity(t); 1400 dm_table_set_integrity(t);
1328 1401
1329 /* 1402 /*