diff options
| author | Eric Paris <eparis@redhat.com> | 2013-11-22 18:57:08 -0500 |
|---|---|---|
| committer | Eric Paris <eparis@redhat.com> | 2013-11-22 18:57:54 -0500 |
| commit | fc582aef7dcc27a7120cf232c1e76c569c7b6eab (patch) | |
| tree | 7d275dd4ceab6067b91e9a25a5f6338b425fbccd /block | |
| parent | 9175c9d2aed528800175ef81c90569d00d23f9be (diff) | |
| parent | 5e01dc7b26d9f24f39abace5da98ccbd6a5ceb52 (diff) | |
Merge tag 'v3.12'
Linux 3.12
Conflicts:
fs/exec.c
Diffstat (limited to 'block')
| -rw-r--r-- | block/Kconfig | 11 | ||||
| -rw-r--r-- | block/Makefile | 1 | ||||
| -rw-r--r-- | block/blk-cgroup.c | 74 | ||||
| -rw-r--r-- | block/blk-cgroup.h | 38 | ||||
| -rw-r--r-- | block/blk-core.c | 12 | ||||
| -rw-r--r-- | block/blk-exec.c | 4 | ||||
| -rw-r--r-- | block/blk-ioc.c | 2 | ||||
| -rw-r--r-- | block/blk-sysfs.c | 2 | ||||
| -rw-r--r-- | block/blk-throttle.c | 43 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 94 | ||||
| -rw-r--r-- | block/cmdline-parser.c | 250 | ||||
| -rw-r--r-- | block/compat_ioctl.c | 2 | ||||
| -rw-r--r-- | block/deadline-iosched.c | 2 | ||||
| -rw-r--r-- | block/elevator.c | 2 | ||||
| -rw-r--r-- | block/genhd.c | 3 | ||||
| -rw-r--r-- | block/partitions/Kconfig | 7 | ||||
| -rw-r--r-- | block/partitions/Makefile | 1 | ||||
| -rw-r--r-- | block/partitions/check.c | 4 | ||||
| -rw-r--r-- | block/partitions/cmdline.c | 99 | ||||
| -rw-r--r-- | block/partitions/cmdline.h | 2 | ||||
| -rw-r--r-- | block/partitions/efi.c | 180 | ||||
| -rw-r--r-- | block/partitions/efi.h | 38 |
22 files changed, 649 insertions, 222 deletions
diff --git a/block/Kconfig b/block/Kconfig index a7e40a7c8214..2429515c05c2 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
| @@ -99,6 +99,17 @@ config BLK_DEV_THROTTLING | |||
| 99 | 99 | ||
| 100 | See Documentation/cgroups/blkio-controller.txt for more information. | 100 | See Documentation/cgroups/blkio-controller.txt for more information. |
| 101 | 101 | ||
| 102 | config BLK_CMDLINE_PARSER | ||
| 103 | bool "Block device command line partition parser" | ||
| 104 | default n | ||
| 105 | ---help--- | ||
| 106 | Enabling this option allows you to specify the partition layout from | ||
| 107 | the kernel boot args. This is typically of use for embedded devices | ||
| 108 | which don't otherwise have any standardized method for listing the | ||
| 109 | partitions on a block device. | ||
| 110 | |||
| 111 | See Documentation/block/cmdline-partition.txt for more information. | ||
| 112 | |||
| 102 | menu "Partition Types" | 113 | menu "Partition Types" |
| 103 | 114 | ||
| 104 | source "block/partitions/Kconfig" | 115 | source "block/partitions/Kconfig" |
diff --git a/block/Makefile b/block/Makefile index 39b76ba66ffd..671a83d063a5 100644 --- a/block/Makefile +++ b/block/Makefile | |||
| @@ -18,3 +18,4 @@ obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o | |||
| 18 | 18 | ||
| 19 | obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o | 19 | obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o |
| 20 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o | 20 | obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o |
| 21 | obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o | ||
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 290792a13e3c..4e491d9b5292 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
| @@ -235,8 +235,13 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
| 235 | blkg->online = true; | 235 | blkg->online = true; |
| 236 | spin_unlock(&blkcg->lock); | 236 | spin_unlock(&blkcg->lock); |
| 237 | 237 | ||
| 238 | if (!ret) | 238 | if (!ret) { |
| 239 | if (blkcg == &blkcg_root) { | ||
| 240 | q->root_blkg = blkg; | ||
| 241 | q->root_rl.blkg = blkg; | ||
| 242 | } | ||
| 239 | return blkg; | 243 | return blkg; |
| 244 | } | ||
| 240 | 245 | ||
| 241 | /* @blkg failed fully initialized, use the usual release path */ | 246 | /* @blkg failed fully initialized, use the usual release path */ |
| 242 | blkg_put(blkg); | 247 | blkg_put(blkg); |
| @@ -335,6 +340,15 @@ static void blkg_destroy(struct blkcg_gq *blkg) | |||
| 335 | rcu_assign_pointer(blkcg->blkg_hint, NULL); | 340 | rcu_assign_pointer(blkcg->blkg_hint, NULL); |
| 336 | 341 | ||
| 337 | /* | 342 | /* |
| 343 | * If root blkg is destroyed. Just clear the pointer since root_rl | ||
| 344 | * does not take reference on root blkg. | ||
| 345 | */ | ||
| 346 | if (blkcg == &blkcg_root) { | ||
| 347 | blkg->q->root_blkg = NULL; | ||
| 348 | blkg->q->root_rl.blkg = NULL; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* | ||
| 338 | * Put the reference taken at the time of creation so that when all | 352 | * Put the reference taken at the time of creation so that when all |
| 339 | * queues are gone, group can be destroyed. | 353 | * queues are gone, group can be destroyed. |
| 340 | */ | 354 | */ |
| @@ -360,13 +374,6 @@ static void blkg_destroy_all(struct request_queue *q) | |||
| 360 | blkg_destroy(blkg); | 374 | blkg_destroy(blkg); |
| 361 | spin_unlock(&blkcg->lock); | 375 | spin_unlock(&blkcg->lock); |
| 362 | } | 376 | } |
| 363 | |||
| 364 | /* | ||
| 365 | * root blkg is destroyed. Just clear the pointer since | ||
| 366 | * root_rl does not take reference on root blkg. | ||
| 367 | */ | ||
| 368 | q->root_blkg = NULL; | ||
| 369 | q->root_rl.blkg = NULL; | ||
| 370 | } | 377 | } |
| 371 | 378 | ||
| 372 | /* | 379 | /* |
| @@ -437,10 +444,10 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl, | |||
| 437 | return &blkg->rl; | 444 | return &blkg->rl; |
| 438 | } | 445 | } |
| 439 | 446 | ||
| 440 | static int blkcg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, | 447 | static int blkcg_reset_stats(struct cgroup_subsys_state *css, |
| 441 | u64 val) | 448 | struct cftype *cftype, u64 val) |
| 442 | { | 449 | { |
| 443 | struct blkcg *blkcg = cgroup_to_blkcg(cgroup); | 450 | struct blkcg *blkcg = css_to_blkcg(css); |
| 444 | struct blkcg_gq *blkg; | 451 | struct blkcg_gq *blkg; |
| 445 | int i; | 452 | int i; |
| 446 | 453 | ||
| @@ -614,15 +621,13 @@ u64 blkg_stat_recursive_sum(struct blkg_policy_data *pd, int off) | |||
| 614 | { | 621 | { |
| 615 | struct blkcg_policy *pol = blkcg_policy[pd->plid]; | 622 | struct blkcg_policy *pol = blkcg_policy[pd->plid]; |
| 616 | struct blkcg_gq *pos_blkg; | 623 | struct blkcg_gq *pos_blkg; |
| 617 | struct cgroup *pos_cgrp; | 624 | struct cgroup_subsys_state *pos_css; |
| 618 | u64 sum; | 625 | u64 sum = 0; |
| 619 | 626 | ||
| 620 | lockdep_assert_held(pd->blkg->q->queue_lock); | 627 | lockdep_assert_held(pd->blkg->q->queue_lock); |
| 621 | 628 | ||
| 622 | sum = blkg_stat_read((void *)pd + off); | ||
| 623 | |||
| 624 | rcu_read_lock(); | 629 | rcu_read_lock(); |
| 625 | blkg_for_each_descendant_pre(pos_blkg, pos_cgrp, pd_to_blkg(pd)) { | 630 | blkg_for_each_descendant_pre(pos_blkg, pos_css, pd_to_blkg(pd)) { |
| 626 | struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol); | 631 | struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol); |
| 627 | struct blkg_stat *stat = (void *)pos_pd + off; | 632 | struct blkg_stat *stat = (void *)pos_pd + off; |
| 628 | 633 | ||
| @@ -649,16 +654,14 @@ struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkg_policy_data *pd, | |||
| 649 | { | 654 | { |
| 650 | struct blkcg_policy *pol = blkcg_policy[pd->plid]; | 655 | struct blkcg_policy *pol = blkcg_policy[pd->plid]; |
| 651 | struct blkcg_gq *pos_blkg; | 656 | struct blkcg_gq *pos_blkg; |
| 652 | struct cgroup *pos_cgrp; | 657 | struct cgroup_subsys_state *pos_css; |
| 653 | struct blkg_rwstat sum; | 658 | struct blkg_rwstat sum = { }; |
| 654 | int i; | 659 | int i; |
| 655 | 660 | ||
| 656 | lockdep_assert_held(pd->blkg->q->queue_lock); | 661 | lockdep_assert_held(pd->blkg->q->queue_lock); |
| 657 | 662 | ||
| 658 | sum = blkg_rwstat_read((void *)pd + off); | ||
| 659 | |||
| 660 | rcu_read_lock(); | 663 | rcu_read_lock(); |
| 661 | blkg_for_each_descendant_pre(pos_blkg, pos_cgrp, pd_to_blkg(pd)) { | 664 | blkg_for_each_descendant_pre(pos_blkg, pos_css, pd_to_blkg(pd)) { |
| 662 | struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol); | 665 | struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol); |
| 663 | struct blkg_rwstat *rwstat = (void *)pos_pd + off; | 666 | struct blkg_rwstat *rwstat = (void *)pos_pd + off; |
| 664 | struct blkg_rwstat tmp; | 667 | struct blkg_rwstat tmp; |
| @@ -765,18 +768,18 @@ struct cftype blkcg_files[] = { | |||
| 765 | 768 | ||
| 766 | /** | 769 | /** |
| 767 | * blkcg_css_offline - cgroup css_offline callback | 770 | * blkcg_css_offline - cgroup css_offline callback |
| 768 | * @cgroup: cgroup of interest | 771 | * @css: css of interest |
| 769 | * | 772 | * |
| 770 | * This function is called when @cgroup is about to go away and responsible | 773 | * This function is called when @css is about to go away and responsible |
| 771 | * for shooting down all blkgs associated with @cgroup. blkgs should be | 774 | * for shooting down all blkgs associated with @css. blkgs should be |
| 772 | * removed while holding both q and blkcg locks. As blkcg lock is nested | 775 | * removed while holding both q and blkcg locks. As blkcg lock is nested |
| 773 | * inside q lock, this function performs reverse double lock dancing. | 776 | * inside q lock, this function performs reverse double lock dancing. |
| 774 | * | 777 | * |
| 775 | * This is the blkcg counterpart of ioc_release_fn(). | 778 | * This is the blkcg counterpart of ioc_release_fn(). |
| 776 | */ | 779 | */ |
| 777 | static void blkcg_css_offline(struct cgroup *cgroup) | 780 | static void blkcg_css_offline(struct cgroup_subsys_state *css) |
| 778 | { | 781 | { |
| 779 | struct blkcg *blkcg = cgroup_to_blkcg(cgroup); | 782 | struct blkcg *blkcg = css_to_blkcg(css); |
| 780 | 783 | ||
| 781 | spin_lock_irq(&blkcg->lock); | 784 | spin_lock_irq(&blkcg->lock); |
| 782 | 785 | ||
| @@ -798,21 +801,21 @@ static void blkcg_css_offline(struct cgroup *cgroup) | |||
| 798 | spin_unlock_irq(&blkcg->lock); | 801 | spin_unlock_irq(&blkcg->lock); |
| 799 | } | 802 | } |
| 800 | 803 | ||
| 801 | static void blkcg_css_free(struct cgroup *cgroup) | 804 | static void blkcg_css_free(struct cgroup_subsys_state *css) |
| 802 | { | 805 | { |
| 803 | struct blkcg *blkcg = cgroup_to_blkcg(cgroup); | 806 | struct blkcg *blkcg = css_to_blkcg(css); |
| 804 | 807 | ||
| 805 | if (blkcg != &blkcg_root) | 808 | if (blkcg != &blkcg_root) |
| 806 | kfree(blkcg); | 809 | kfree(blkcg); |
| 807 | } | 810 | } |
| 808 | 811 | ||
| 809 | static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup) | 812 | static struct cgroup_subsys_state * |
| 813 | blkcg_css_alloc(struct cgroup_subsys_state *parent_css) | ||
| 810 | { | 814 | { |
| 811 | static atomic64_t id_seq = ATOMIC64_INIT(0); | 815 | static atomic64_t id_seq = ATOMIC64_INIT(0); |
| 812 | struct blkcg *blkcg; | 816 | struct blkcg *blkcg; |
| 813 | struct cgroup *parent = cgroup->parent; | ||
| 814 | 817 | ||
| 815 | if (!parent) { | 818 | if (!parent_css) { |
| 816 | blkcg = &blkcg_root; | 819 | blkcg = &blkcg_root; |
| 817 | goto done; | 820 | goto done; |
| 818 | } | 821 | } |
| @@ -883,14 +886,15 @@ void blkcg_exit_queue(struct request_queue *q) | |||
| 883 | * of the main cic data structures. For now we allow a task to change | 886 | * of the main cic data structures. For now we allow a task to change |
| 884 | * its cgroup only if it's the only owner of its ioc. | 887 | * its cgroup only if it's the only owner of its ioc. |
| 885 | */ | 888 | */ |
| 886 | static int blkcg_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) | 889 | static int blkcg_can_attach(struct cgroup_subsys_state *css, |
| 890 | struct cgroup_taskset *tset) | ||
| 887 | { | 891 | { |
| 888 | struct task_struct *task; | 892 | struct task_struct *task; |
| 889 | struct io_context *ioc; | 893 | struct io_context *ioc; |
| 890 | int ret = 0; | 894 | int ret = 0; |
| 891 | 895 | ||
| 892 | /* task_lock() is needed to avoid races with exit_io_context() */ | 896 | /* task_lock() is needed to avoid races with exit_io_context() */ |
| 893 | cgroup_taskset_for_each(task, cgrp, tset) { | 897 | cgroup_taskset_for_each(task, css, tset) { |
| 894 | task_lock(task); | 898 | task_lock(task); |
| 895 | ioc = task->io_context; | 899 | ioc = task->io_context; |
| 896 | if (ioc && atomic_read(&ioc->nr_tasks) > 1) | 900 | if (ioc && atomic_read(&ioc->nr_tasks) > 1) |
| @@ -973,8 +977,6 @@ int blkcg_activate_policy(struct request_queue *q, | |||
| 973 | ret = PTR_ERR(blkg); | 977 | ret = PTR_ERR(blkg); |
| 974 | goto out_unlock; | 978 | goto out_unlock; |
| 975 | } | 979 | } |
| 976 | q->root_blkg = blkg; | ||
| 977 | q->root_rl.blkg = blkg; | ||
| 978 | 980 | ||
| 979 | list_for_each_entry(blkg, &q->blkg_list, q_node) | 981 | list_for_each_entry(blkg, &q->blkg_list, q_node) |
| 980 | cnt++; | 982 | cnt++; |
| @@ -1127,7 +1129,7 @@ void blkcg_policy_unregister(struct blkcg_policy *pol) | |||
| 1127 | 1129 | ||
| 1128 | /* kill the intf files first */ | 1130 | /* kill the intf files first */ |
| 1129 | if (pol->cftypes) | 1131 | if (pol->cftypes) |
| 1130 | cgroup_rm_cftypes(&blkio_subsys, pol->cftypes); | 1132 | cgroup_rm_cftypes(pol->cftypes); |
| 1131 | 1133 | ||
| 1132 | /* unregister and update blkgs */ | 1134 | /* unregister and update blkgs */ |
| 1133 | blkcg_policy[pol->plid] = NULL; | 1135 | blkcg_policy[pol->plid] = NULL; |
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 8056c03a3382..ae6969a7ffd4 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
| @@ -179,22 +179,20 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, | |||
| 179 | void blkg_conf_finish(struct blkg_conf_ctx *ctx); | 179 | void blkg_conf_finish(struct blkg_conf_ctx *ctx); |
| 180 | 180 | ||
| 181 | 181 | ||
| 182 | static inline struct blkcg *cgroup_to_blkcg(struct cgroup *cgroup) | 182 | static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) |
| 183 | { | 183 | { |
| 184 | return container_of(cgroup_subsys_state(cgroup, blkio_subsys_id), | 184 | return css ? container_of(css, struct blkcg, css) : NULL; |
| 185 | struct blkcg, css); | ||
| 186 | } | 185 | } |
| 187 | 186 | ||
| 188 | static inline struct blkcg *task_blkcg(struct task_struct *tsk) | 187 | static inline struct blkcg *task_blkcg(struct task_struct *tsk) |
| 189 | { | 188 | { |
| 190 | return container_of(task_subsys_state(tsk, blkio_subsys_id), | 189 | return css_to_blkcg(task_css(tsk, blkio_subsys_id)); |
| 191 | struct blkcg, css); | ||
| 192 | } | 190 | } |
| 193 | 191 | ||
| 194 | static inline struct blkcg *bio_blkcg(struct bio *bio) | 192 | static inline struct blkcg *bio_blkcg(struct bio *bio) |
| 195 | { | 193 | { |
| 196 | if (bio && bio->bi_css) | 194 | if (bio && bio->bi_css) |
| 197 | return container_of(bio->bi_css, struct blkcg, css); | 195 | return css_to_blkcg(bio->bi_css); |
| 198 | return task_blkcg(current); | 196 | return task_blkcg(current); |
| 199 | } | 197 | } |
| 200 | 198 | ||
| @@ -206,9 +204,7 @@ static inline struct blkcg *bio_blkcg(struct bio *bio) | |||
| 206 | */ | 204 | */ |
| 207 | static inline struct blkcg *blkcg_parent(struct blkcg *blkcg) | 205 | static inline struct blkcg *blkcg_parent(struct blkcg *blkcg) |
| 208 | { | 206 | { |
| 209 | struct cgroup *pcg = blkcg->css.cgroup->parent; | 207 | return css_to_blkcg(css_parent(&blkcg->css)); |
| 210 | |||
| 211 | return pcg ? cgroup_to_blkcg(pcg) : NULL; | ||
| 212 | } | 208 | } |
| 213 | 209 | ||
| 214 | /** | 210 | /** |
| @@ -288,32 +284,33 @@ struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q, | |||
| 288 | /** | 284 | /** |
| 289 | * blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants | 285 | * blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants |
| 290 | * @d_blkg: loop cursor pointing to the current descendant | 286 | * @d_blkg: loop cursor pointing to the current descendant |
| 291 | * @pos_cgrp: used for iteration | 287 | * @pos_css: used for iteration |
| 292 | * @p_blkg: target blkg to walk descendants of | 288 | * @p_blkg: target blkg to walk descendants of |
| 293 | * | 289 | * |
| 294 | * Walk @c_blkg through the descendants of @p_blkg. Must be used with RCU | 290 | * Walk @c_blkg through the descendants of @p_blkg. Must be used with RCU |
| 295 | * read locked. If called under either blkcg or queue lock, the iteration | 291 | * read locked. If called under either blkcg or queue lock, the iteration |
| 296 | * is guaranteed to include all and only online blkgs. The caller may | 292 | * is guaranteed to include all and only online blkgs. The caller may |
| 297 | * update @pos_cgrp by calling cgroup_rightmost_descendant() to skip | 293 | * update @pos_css by calling css_rightmost_descendant() to skip subtree. |
| 298 | * subtree. | 294 | * @p_blkg is included in the iteration and the first node to be visited. |
| 299 | */ | 295 | */ |
| 300 | #define blkg_for_each_descendant_pre(d_blkg, pos_cgrp, p_blkg) \ | 296 | #define blkg_for_each_descendant_pre(d_blkg, pos_css, p_blkg) \ |
| 301 | cgroup_for_each_descendant_pre((pos_cgrp), (p_blkg)->blkcg->css.cgroup) \ | 297 | css_for_each_descendant_pre((pos_css), &(p_blkg)->blkcg->css) \ |
| 302 | if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ | 298 | if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \ |
| 303 | (p_blkg)->q, false))) | 299 | (p_blkg)->q, false))) |
| 304 | 300 | ||
| 305 | /** | 301 | /** |
| 306 | * blkg_for_each_descendant_post - post-order walk of a blkg's descendants | 302 | * blkg_for_each_descendant_post - post-order walk of a blkg's descendants |
| 307 | * @d_blkg: loop cursor pointing to the current descendant | 303 | * @d_blkg: loop cursor pointing to the current descendant |
| 308 | * @pos_cgrp: used for iteration | 304 | * @pos_css: used for iteration |
| 309 | * @p_blkg: target blkg to walk descendants of | 305 | * @p_blkg: target blkg to walk descendants of |
| 310 | * | 306 | * |
| 311 | * Similar to blkg_for_each_descendant_pre() but performs post-order | 307 | * Similar to blkg_for_each_descendant_pre() but performs post-order |
| 312 | * traversal instead. Synchronization rules are the same. | 308 | * traversal instead. Synchronization rules are the same. @p_blkg is |
| 309 | * included in the iteration and the last node to be visited. | ||
| 313 | */ | 310 | */ |
| 314 | #define blkg_for_each_descendant_post(d_blkg, pos_cgrp, p_blkg) \ | 311 | #define blkg_for_each_descendant_post(d_blkg, pos_css, p_blkg) \ |
| 315 | cgroup_for_each_descendant_post((pos_cgrp), (p_blkg)->blkcg->css.cgroup) \ | 312 | css_for_each_descendant_post((pos_css), &(p_blkg)->blkcg->css) \ |
| 316 | if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ | 313 | if (((d_blkg) = __blkg_lookup(css_to_blkcg(pos_css), \ |
| 317 | (p_blkg)->q, false))) | 314 | (p_blkg)->q, false))) |
| 318 | 315 | ||
| 319 | /** | 316 | /** |
| @@ -576,7 +573,6 @@ static inline int blkcg_activate_policy(struct request_queue *q, | |||
| 576 | static inline void blkcg_deactivate_policy(struct request_queue *q, | 573 | static inline void blkcg_deactivate_policy(struct request_queue *q, |
| 577 | const struct blkcg_policy *pol) { } | 574 | const struct blkcg_policy *pol) { } |
| 578 | 575 | ||
| 579 | static inline struct blkcg *cgroup_to_blkcg(struct cgroup *cgroup) { return NULL; } | ||
| 580 | static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } | 576 | static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } |
| 581 | 577 | ||
| 582 | static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg, | 578 | static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg, |
diff --git a/block/blk-core.c b/block/blk-core.c index 93a18d1d3da8..0a00e4ecf87c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -1549,11 +1549,9 @@ get_rq: | |||
| 1549 | if (plug) { | 1549 | if (plug) { |
| 1550 | /* | 1550 | /* |
| 1551 | * If this is the first request added after a plug, fire | 1551 | * If this is the first request added after a plug, fire |
| 1552 | * of a plug trace. If others have been added before, check | 1552 | * of a plug trace. |
| 1553 | * if we have multiple devices in this plug. If so, make a | ||
| 1554 | * note to sort the list before dispatch. | ||
| 1555 | */ | 1553 | */ |
| 1556 | if (list_empty(&plug->list)) | 1554 | if (!request_count) |
| 1557 | trace_block_plug(q); | 1555 | trace_block_plug(q); |
| 1558 | else { | 1556 | else { |
| 1559 | if (request_count >= BLK_MAX_REQUEST_COUNT) { | 1557 | if (request_count >= BLK_MAX_REQUEST_COUNT) { |
| @@ -2318,6 +2316,12 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) | |||
| 2318 | case -ETIMEDOUT: | 2316 | case -ETIMEDOUT: |
| 2319 | error_type = "timeout"; | 2317 | error_type = "timeout"; |
| 2320 | break; | 2318 | break; |
| 2319 | case -ENOSPC: | ||
| 2320 | error_type = "critical space allocation"; | ||
| 2321 | break; | ||
| 2322 | case -ENODATA: | ||
| 2323 | error_type = "critical medium"; | ||
| 2324 | break; | ||
| 2321 | case -EIO: | 2325 | case -EIO: |
| 2322 | default: | 2326 | default: |
| 2323 | error_type = "I/O"; | 2327 | error_type = "I/O"; |
diff --git a/block/blk-exec.c b/block/blk-exec.c index e70621396129..ae4f27d7944e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c | |||
| @@ -68,9 +68,9 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, | |||
| 68 | spin_lock_irq(q->queue_lock); | 68 | spin_lock_irq(q->queue_lock); |
| 69 | 69 | ||
| 70 | if (unlikely(blk_queue_dying(q))) { | 70 | if (unlikely(blk_queue_dying(q))) { |
| 71 | rq->cmd_flags |= REQ_QUIET; | ||
| 71 | rq->errors = -ENXIO; | 72 | rq->errors = -ENXIO; |
| 72 | if (rq->end_io) | 73 | __blk_end_request_all(rq, rq->errors); |
| 73 | rq->end_io(rq, rq->errors); | ||
| 74 | spin_unlock_irq(q->queue_lock); | 74 | spin_unlock_irq(q->queue_lock); |
| 75 | return; | 75 | return; |
| 76 | } | 76 | } |
diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 4464c823cff2..46cd7bd18b34 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c | |||
| @@ -367,7 +367,7 @@ struct io_cq *ioc_create_icq(struct io_context *ioc, struct request_queue *q, | |||
| 367 | if (!icq) | 367 | if (!icq) |
| 368 | return NULL; | 368 | return NULL; |
| 369 | 369 | ||
| 370 | if (radix_tree_preload(gfp_mask) < 0) { | 370 | if (radix_tree_maybe_preload(gfp_mask) < 0) { |
| 371 | kmem_cache_free(et->icq_cache, icq); | 371 | kmem_cache_free(et->icq_cache, icq); |
| 372 | return NULL; | 372 | return NULL; |
| 373 | } | 373 | } |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 5efc5a647183..3aa5b195f4dd 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
| @@ -29,7 +29,7 @@ queue_var_store(unsigned long *var, const char *page, size_t count) | |||
| 29 | int err; | 29 | int err; |
| 30 | unsigned long v; | 30 | unsigned long v; |
| 31 | 31 | ||
| 32 | err = strict_strtoul(page, 10, &v); | 32 | err = kstrtoul(page, 10, &v); |
| 33 | if (err || v > UINT_MAX) | 33 | if (err || v > UINT_MAX) |
| 34 | return -EINVAL; | 34 | return -EINVAL; |
| 35 | 35 | ||
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 08a32dfd3844..8331aba9426f 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
| @@ -1293,10 +1293,10 @@ static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, | |||
| 1293 | return __blkg_prfill_rwstat(sf, pd, &rwstat); | 1293 | return __blkg_prfill_rwstat(sf, pd, &rwstat); |
| 1294 | } | 1294 | } |
| 1295 | 1295 | ||
| 1296 | static int tg_print_cpu_rwstat(struct cgroup *cgrp, struct cftype *cft, | 1296 | static int tg_print_cpu_rwstat(struct cgroup_subsys_state *css, |
| 1297 | struct seq_file *sf) | 1297 | struct cftype *cft, struct seq_file *sf) |
| 1298 | { | 1298 | { |
| 1299 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1299 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1300 | 1300 | ||
| 1301 | blkcg_print_blkgs(sf, blkcg, tg_prfill_cpu_rwstat, &blkcg_policy_throtl, | 1301 | blkcg_print_blkgs(sf, blkcg, tg_prfill_cpu_rwstat, &blkcg_policy_throtl, |
| 1302 | cft->private, true); | 1302 | cft->private, true); |
| @@ -1325,31 +1325,31 @@ static u64 tg_prfill_conf_uint(struct seq_file *sf, struct blkg_policy_data *pd, | |||
| 1325 | return __blkg_prfill_u64(sf, pd, v); | 1325 | return __blkg_prfill_u64(sf, pd, v); |
| 1326 | } | 1326 | } |
| 1327 | 1327 | ||
| 1328 | static int tg_print_conf_u64(struct cgroup *cgrp, struct cftype *cft, | 1328 | static int tg_print_conf_u64(struct cgroup_subsys_state *css, |
| 1329 | struct seq_file *sf) | 1329 | struct cftype *cft, struct seq_file *sf) |
| 1330 | { | 1330 | { |
| 1331 | blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp), tg_prfill_conf_u64, | 1331 | blkcg_print_blkgs(sf, css_to_blkcg(css), tg_prfill_conf_u64, |
| 1332 | &blkcg_policy_throtl, cft->private, false); | 1332 | &blkcg_policy_throtl, cft->private, false); |
| 1333 | return 0; | 1333 | return 0; |
| 1334 | } | 1334 | } |
| 1335 | 1335 | ||
| 1336 | static int tg_print_conf_uint(struct cgroup *cgrp, struct cftype *cft, | 1336 | static int tg_print_conf_uint(struct cgroup_subsys_state *css, |
| 1337 | struct seq_file *sf) | 1337 | struct cftype *cft, struct seq_file *sf) |
| 1338 | { | 1338 | { |
| 1339 | blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp), tg_prfill_conf_uint, | 1339 | blkcg_print_blkgs(sf, css_to_blkcg(css), tg_prfill_conf_uint, |
| 1340 | &blkcg_policy_throtl, cft->private, false); | 1340 | &blkcg_policy_throtl, cft->private, false); |
| 1341 | return 0; | 1341 | return 0; |
| 1342 | } | 1342 | } |
| 1343 | 1343 | ||
| 1344 | static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, | 1344 | static int tg_set_conf(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1345 | bool is_u64) | 1345 | const char *buf, bool is_u64) |
| 1346 | { | 1346 | { |
| 1347 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1347 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1348 | struct blkg_conf_ctx ctx; | 1348 | struct blkg_conf_ctx ctx; |
| 1349 | struct throtl_grp *tg; | 1349 | struct throtl_grp *tg; |
| 1350 | struct throtl_service_queue *sq; | 1350 | struct throtl_service_queue *sq; |
| 1351 | struct blkcg_gq *blkg; | 1351 | struct blkcg_gq *blkg; |
| 1352 | struct cgroup *pos_cgrp; | 1352 | struct cgroup_subsys_state *pos_css; |
| 1353 | int ret; | 1353 | int ret; |
| 1354 | 1354 | ||
| 1355 | ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx); | 1355 | ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx); |
| @@ -1379,8 +1379,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, | |||
| 1379 | * restrictions in the whole hierarchy and allows them to bypass | 1379 | * restrictions in the whole hierarchy and allows them to bypass |
| 1380 | * blk-throttle. | 1380 | * blk-throttle. |
| 1381 | */ | 1381 | */ |
| 1382 | tg_update_has_rules(tg); | 1382 | blkg_for_each_descendant_pre(blkg, pos_css, ctx.blkg) |
| 1383 | blkg_for_each_descendant_pre(blkg, pos_cgrp, ctx.blkg) | ||
| 1384 | tg_update_has_rules(blkg_to_tg(blkg)); | 1383 | tg_update_has_rules(blkg_to_tg(blkg)); |
| 1385 | 1384 | ||
| 1386 | /* | 1385 | /* |
| @@ -1403,16 +1402,16 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, | |||
| 1403 | return 0; | 1402 | return 0; |
| 1404 | } | 1403 | } |
| 1405 | 1404 | ||
| 1406 | static int tg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft, | 1405 | static int tg_set_conf_u64(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1407 | const char *buf) | 1406 | const char *buf) |
| 1408 | { | 1407 | { |
| 1409 | return tg_set_conf(cgrp, cft, buf, true); | 1408 | return tg_set_conf(css, cft, buf, true); |
| 1410 | } | 1409 | } |
| 1411 | 1410 | ||
| 1412 | static int tg_set_conf_uint(struct cgroup *cgrp, struct cftype *cft, | 1411 | static int tg_set_conf_uint(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1413 | const char *buf) | 1412 | const char *buf) |
| 1414 | { | 1413 | { |
| 1415 | return tg_set_conf(cgrp, cft, buf, false); | 1414 | return tg_set_conf(css, cft, buf, false); |
| 1416 | } | 1415 | } |
| 1417 | 1416 | ||
| 1418 | static struct cftype throtl_files[] = { | 1417 | static struct cftype throtl_files[] = { |
| @@ -1623,7 +1622,7 @@ void blk_throtl_drain(struct request_queue *q) | |||
| 1623 | { | 1622 | { |
| 1624 | struct throtl_data *td = q->td; | 1623 | struct throtl_data *td = q->td; |
| 1625 | struct blkcg_gq *blkg; | 1624 | struct blkcg_gq *blkg; |
| 1626 | struct cgroup *pos_cgrp; | 1625 | struct cgroup_subsys_state *pos_css; |
| 1627 | struct bio *bio; | 1626 | struct bio *bio; |
| 1628 | int rw; | 1627 | int rw; |
| 1629 | 1628 | ||
| @@ -1636,11 +1635,9 @@ void blk_throtl_drain(struct request_queue *q) | |||
| 1636 | * better to walk service_queue tree directly but blkg walk is | 1635 | * better to walk service_queue tree directly but blkg walk is |
| 1637 | * easier. | 1636 | * easier. |
| 1638 | */ | 1637 | */ |
| 1639 | blkg_for_each_descendant_post(blkg, pos_cgrp, td->queue->root_blkg) | 1638 | blkg_for_each_descendant_post(blkg, pos_css, td->queue->root_blkg) |
| 1640 | tg_drain_bios(&blkg_to_tg(blkg)->service_queue); | 1639 | tg_drain_bios(&blkg_to_tg(blkg)->service_queue); |
| 1641 | 1640 | ||
| 1642 | tg_drain_bios(&td_root_tg(td)->service_queue); | ||
| 1643 | |||
| 1644 | /* finally, transfer bios from top-level tg's into the td */ | 1641 | /* finally, transfer bios from top-level tg's into the td */ |
| 1645 | tg_drain_bios(&td->service_queue); | 1642 | tg_drain_bios(&td->service_queue); |
| 1646 | 1643 | ||
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index d5bbdcfd0dab..434944cbd761 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -1607,12 +1607,11 @@ static u64 cfqg_prfill_weight_device(struct seq_file *sf, | |||
| 1607 | return __blkg_prfill_u64(sf, pd, cfqg->dev_weight); | 1607 | return __blkg_prfill_u64(sf, pd, cfqg->dev_weight); |
| 1608 | } | 1608 | } |
| 1609 | 1609 | ||
| 1610 | static int cfqg_print_weight_device(struct cgroup *cgrp, struct cftype *cft, | 1610 | static int cfqg_print_weight_device(struct cgroup_subsys_state *css, |
| 1611 | struct seq_file *sf) | 1611 | struct cftype *cft, struct seq_file *sf) |
| 1612 | { | 1612 | { |
| 1613 | blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp), | 1613 | blkcg_print_blkgs(sf, css_to_blkcg(css), cfqg_prfill_weight_device, |
| 1614 | cfqg_prfill_weight_device, &blkcg_policy_cfq, 0, | 1614 | &blkcg_policy_cfq, 0, false); |
| 1615 | false); | ||
| 1616 | return 0; | 1615 | return 0; |
| 1617 | } | 1616 | } |
| 1618 | 1617 | ||
| @@ -1626,35 +1625,34 @@ static u64 cfqg_prfill_leaf_weight_device(struct seq_file *sf, | |||
| 1626 | return __blkg_prfill_u64(sf, pd, cfqg->dev_leaf_weight); | 1625 | return __blkg_prfill_u64(sf, pd, cfqg->dev_leaf_weight); |
| 1627 | } | 1626 | } |
| 1628 | 1627 | ||
| 1629 | static int cfqg_print_leaf_weight_device(struct cgroup *cgrp, | 1628 | static int cfqg_print_leaf_weight_device(struct cgroup_subsys_state *css, |
| 1630 | struct cftype *cft, | 1629 | struct cftype *cft, |
| 1631 | struct seq_file *sf) | 1630 | struct seq_file *sf) |
| 1632 | { | 1631 | { |
| 1633 | blkcg_print_blkgs(sf, cgroup_to_blkcg(cgrp), | 1632 | blkcg_print_blkgs(sf, css_to_blkcg(css), cfqg_prfill_leaf_weight_device, |
| 1634 | cfqg_prfill_leaf_weight_device, &blkcg_policy_cfq, 0, | 1633 | &blkcg_policy_cfq, 0, false); |
| 1635 | false); | ||
| 1636 | return 0; | 1634 | return 0; |
| 1637 | } | 1635 | } |
| 1638 | 1636 | ||
| 1639 | static int cfq_print_weight(struct cgroup *cgrp, struct cftype *cft, | 1637 | static int cfq_print_weight(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1640 | struct seq_file *sf) | 1638 | struct seq_file *sf) |
| 1641 | { | 1639 | { |
| 1642 | seq_printf(sf, "%u\n", cgroup_to_blkcg(cgrp)->cfq_weight); | 1640 | seq_printf(sf, "%u\n", css_to_blkcg(css)->cfq_weight); |
| 1643 | return 0; | 1641 | return 0; |
| 1644 | } | 1642 | } |
| 1645 | 1643 | ||
| 1646 | static int cfq_print_leaf_weight(struct cgroup *cgrp, struct cftype *cft, | 1644 | static int cfq_print_leaf_weight(struct cgroup_subsys_state *css, |
| 1647 | struct seq_file *sf) | 1645 | struct cftype *cft, struct seq_file *sf) |
| 1648 | { | 1646 | { |
| 1649 | seq_printf(sf, "%u\n", | 1647 | seq_printf(sf, "%u\n", css_to_blkcg(css)->cfq_leaf_weight); |
| 1650 | cgroup_to_blkcg(cgrp)->cfq_leaf_weight); | ||
| 1651 | return 0; | 1648 | return 0; |
| 1652 | } | 1649 | } |
| 1653 | 1650 | ||
| 1654 | static int __cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft, | 1651 | static int __cfqg_set_weight_device(struct cgroup_subsys_state *css, |
| 1655 | const char *buf, bool is_leaf_weight) | 1652 | struct cftype *cft, const char *buf, |
| 1653 | bool is_leaf_weight) | ||
| 1656 | { | 1654 | { |
| 1657 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1655 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1658 | struct blkg_conf_ctx ctx; | 1656 | struct blkg_conf_ctx ctx; |
| 1659 | struct cfq_group *cfqg; | 1657 | struct cfq_group *cfqg; |
| 1660 | int ret; | 1658 | int ret; |
| @@ -1680,22 +1678,22 @@ static int __cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft, | |||
| 1680 | return ret; | 1678 | return ret; |
| 1681 | } | 1679 | } |
| 1682 | 1680 | ||
| 1683 | static int cfqg_set_weight_device(struct cgroup *cgrp, struct cftype *cft, | 1681 | static int cfqg_set_weight_device(struct cgroup_subsys_state *css, |
| 1684 | const char *buf) | 1682 | struct cftype *cft, const char *buf) |
| 1685 | { | 1683 | { |
| 1686 | return __cfqg_set_weight_device(cgrp, cft, buf, false); | 1684 | return __cfqg_set_weight_device(css, cft, buf, false); |
| 1687 | } | 1685 | } |
| 1688 | 1686 | ||
| 1689 | static int cfqg_set_leaf_weight_device(struct cgroup *cgrp, struct cftype *cft, | 1687 | static int cfqg_set_leaf_weight_device(struct cgroup_subsys_state *css, |
| 1690 | const char *buf) | 1688 | struct cftype *cft, const char *buf) |
| 1691 | { | 1689 | { |
| 1692 | return __cfqg_set_weight_device(cgrp, cft, buf, true); | 1690 | return __cfqg_set_weight_device(css, cft, buf, true); |
| 1693 | } | 1691 | } |
| 1694 | 1692 | ||
| 1695 | static int __cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val, | 1693 | static int __cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1696 | bool is_leaf_weight) | 1694 | u64 val, bool is_leaf_weight) |
| 1697 | { | 1695 | { |
| 1698 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1696 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1699 | struct blkcg_gq *blkg; | 1697 | struct blkcg_gq *blkg; |
| 1700 | 1698 | ||
| 1701 | if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX) | 1699 | if (val < CFQ_WEIGHT_MIN || val > CFQ_WEIGHT_MAX) |
| @@ -1727,30 +1725,32 @@ static int __cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val, | |||
| 1727 | return 0; | 1725 | return 0; |
| 1728 | } | 1726 | } |
| 1729 | 1727 | ||
| 1730 | static int cfq_set_weight(struct cgroup *cgrp, struct cftype *cft, u64 val) | 1728 | static int cfq_set_weight(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1729 | u64 val) | ||
| 1731 | { | 1730 | { |
| 1732 | return __cfq_set_weight(cgrp, cft, val, false); | 1731 | return __cfq_set_weight(css, cft, val, false); |
| 1733 | } | 1732 | } |
| 1734 | 1733 | ||
| 1735 | static int cfq_set_leaf_weight(struct cgroup *cgrp, struct cftype *cft, u64 val) | 1734 | static int cfq_set_leaf_weight(struct cgroup_subsys_state *css, |
| 1735 | struct cftype *cft, u64 val) | ||
| 1736 | { | 1736 | { |
| 1737 | return __cfq_set_weight(cgrp, cft, val, true); | 1737 | return __cfq_set_weight(css, cft, val, true); |
| 1738 | } | 1738 | } |
| 1739 | 1739 | ||
| 1740 | static int cfqg_print_stat(struct cgroup *cgrp, struct cftype *cft, | 1740 | static int cfqg_print_stat(struct cgroup_subsys_state *css, struct cftype *cft, |
| 1741 | struct seq_file *sf) | 1741 | struct seq_file *sf) |
| 1742 | { | 1742 | { |
| 1743 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1743 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1744 | 1744 | ||
| 1745 | blkcg_print_blkgs(sf, blkcg, blkg_prfill_stat, &blkcg_policy_cfq, | 1745 | blkcg_print_blkgs(sf, blkcg, blkg_prfill_stat, &blkcg_policy_cfq, |
| 1746 | cft->private, false); | 1746 | cft->private, false); |
| 1747 | return 0; | 1747 | return 0; |
| 1748 | } | 1748 | } |
| 1749 | 1749 | ||
| 1750 | static int cfqg_print_rwstat(struct cgroup *cgrp, struct cftype *cft, | 1750 | static int cfqg_print_rwstat(struct cgroup_subsys_state *css, |
| 1751 | struct seq_file *sf) | 1751 | struct cftype *cft, struct seq_file *sf) |
| 1752 | { | 1752 | { |
| 1753 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1753 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1754 | 1754 | ||
| 1755 | blkcg_print_blkgs(sf, blkcg, blkg_prfill_rwstat, &blkcg_policy_cfq, | 1755 | blkcg_print_blkgs(sf, blkcg, blkg_prfill_rwstat, &blkcg_policy_cfq, |
| 1756 | cft->private, true); | 1756 | cft->private, true); |
| @@ -1773,20 +1773,20 @@ static u64 cfqg_prfill_rwstat_recursive(struct seq_file *sf, | |||
| 1773 | return __blkg_prfill_rwstat(sf, pd, &sum); | 1773 | return __blkg_prfill_rwstat(sf, pd, &sum); |
| 1774 | } | 1774 | } |
| 1775 | 1775 | ||
| 1776 | static int cfqg_print_stat_recursive(struct cgroup *cgrp, struct cftype *cft, | 1776 | static int cfqg_print_stat_recursive(struct cgroup_subsys_state *css, |
| 1777 | struct seq_file *sf) | 1777 | struct cftype *cft, struct seq_file *sf) |
| 1778 | { | 1778 | { |
| 1779 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1779 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1780 | 1780 | ||
| 1781 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_stat_recursive, | 1781 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_stat_recursive, |
| 1782 | &blkcg_policy_cfq, cft->private, false); | 1782 | &blkcg_policy_cfq, cft->private, false); |
| 1783 | return 0; | 1783 | return 0; |
| 1784 | } | 1784 | } |
| 1785 | 1785 | ||
| 1786 | static int cfqg_print_rwstat_recursive(struct cgroup *cgrp, struct cftype *cft, | 1786 | static int cfqg_print_rwstat_recursive(struct cgroup_subsys_state *css, |
| 1787 | struct seq_file *sf) | 1787 | struct cftype *cft, struct seq_file *sf) |
| 1788 | { | 1788 | { |
| 1789 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1789 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1790 | 1790 | ||
| 1791 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_rwstat_recursive, | 1791 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_rwstat_recursive, |
| 1792 | &blkcg_policy_cfq, cft->private, true); | 1792 | &blkcg_policy_cfq, cft->private, true); |
| @@ -1803,17 +1803,17 @@ static u64 cfqg_prfill_avg_queue_size(struct seq_file *sf, | |||
| 1803 | 1803 | ||
| 1804 | if (samples) { | 1804 | if (samples) { |
| 1805 | v = blkg_stat_read(&cfqg->stats.avg_queue_size_sum); | 1805 | v = blkg_stat_read(&cfqg->stats.avg_queue_size_sum); |
| 1806 | do_div(v, samples); | 1806 | v = div64_u64(v, samples); |
| 1807 | } | 1807 | } |
| 1808 | __blkg_prfill_u64(sf, pd, v); | 1808 | __blkg_prfill_u64(sf, pd, v); |
| 1809 | return 0; | 1809 | return 0; |
| 1810 | } | 1810 | } |
| 1811 | 1811 | ||
| 1812 | /* print avg_queue_size */ | 1812 | /* print avg_queue_size */ |
| 1813 | static int cfqg_print_avg_queue_size(struct cgroup *cgrp, struct cftype *cft, | 1813 | static int cfqg_print_avg_queue_size(struct cgroup_subsys_state *css, |
| 1814 | struct seq_file *sf) | 1814 | struct cftype *cft, struct seq_file *sf) |
| 1815 | { | 1815 | { |
| 1816 | struct blkcg *blkcg = cgroup_to_blkcg(cgrp); | 1816 | struct blkcg *blkcg = css_to_blkcg(css); |
| 1817 | 1817 | ||
| 1818 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_avg_queue_size, | 1818 | blkcg_print_blkgs(sf, blkcg, cfqg_prfill_avg_queue_size, |
| 1819 | &blkcg_policy_cfq, 0, false); | 1819 | &blkcg_policy_cfq, 0, false); |
| @@ -4358,7 +4358,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) | |||
| 4358 | if (!eq) | 4358 | if (!eq) |
| 4359 | return -ENOMEM; | 4359 | return -ENOMEM; |
| 4360 | 4360 | ||
| 4361 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); | 4361 | cfqd = kzalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node); |
| 4362 | if (!cfqd) { | 4362 | if (!cfqd) { |
| 4363 | kobject_put(&eq->kobj); | 4363 | kobject_put(&eq->kobj); |
| 4364 | return -ENOMEM; | 4364 | return -ENOMEM; |
diff --git a/block/cmdline-parser.c b/block/cmdline-parser.c new file mode 100644 index 000000000000..cc2637f8674e --- /dev/null +++ b/block/cmdline-parser.c | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | /* | ||
| 2 | * Parse command line, get partition information | ||
| 3 | * | ||
| 4 | * Written by Cai Zhiyong <caizhiyong@huawei.com> | ||
| 5 | * | ||
| 6 | */ | ||
| 7 | #include <linux/buffer_head.h> | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/cmdline-parser.h> | ||
| 10 | |||
| 11 | static int parse_subpart(struct cmdline_subpart **subpart, char *partdef) | ||
| 12 | { | ||
| 13 | int ret = 0; | ||
| 14 | struct cmdline_subpart *new_subpart; | ||
| 15 | |||
| 16 | *subpart = NULL; | ||
| 17 | |||
| 18 | new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL); | ||
| 19 | if (!new_subpart) | ||
| 20 | return -ENOMEM; | ||
| 21 | |||
| 22 | if (*partdef == '-') { | ||
| 23 | new_subpart->size = (sector_t)(~0ULL); | ||
| 24 | partdef++; | ||
| 25 | } else { | ||
| 26 | new_subpart->size = (sector_t)memparse(partdef, &partdef); | ||
| 27 | if (new_subpart->size < (sector_t)PAGE_SIZE) { | ||
| 28 | pr_warn("cmdline partition size is invalid."); | ||
| 29 | ret = -EINVAL; | ||
| 30 | goto fail; | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | if (*partdef == '@') { | ||
| 35 | partdef++; | ||
| 36 | new_subpart->from = (sector_t)memparse(partdef, &partdef); | ||
| 37 | } else { | ||
| 38 | new_subpart->from = (sector_t)(~0ULL); | ||
| 39 | } | ||
| 40 | |||
| 41 | if (*partdef == '(') { | ||
| 42 | int length; | ||
| 43 | char *next = strchr(++partdef, ')'); | ||
| 44 | |||
| 45 | if (!next) { | ||
| 46 | pr_warn("cmdline partition format is invalid."); | ||
| 47 | ret = -EINVAL; | ||
| 48 | goto fail; | ||
| 49 | } | ||
| 50 | |||
| 51 | length = min_t(int, next - partdef, | ||
| 52 | sizeof(new_subpart->name) - 1); | ||
| 53 | strncpy(new_subpart->name, partdef, length); | ||
| 54 | new_subpart->name[length] = '\0'; | ||
| 55 | |||
| 56 | partdef = ++next; | ||
| 57 | } else | ||
| 58 | new_subpart->name[0] = '\0'; | ||
| 59 | |||
| 60 | new_subpart->flags = 0; | ||
| 61 | |||
| 62 | if (!strncmp(partdef, "ro", 2)) { | ||
| 63 | new_subpart->flags |= PF_RDONLY; | ||
| 64 | partdef += 2; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (!strncmp(partdef, "lk", 2)) { | ||
| 68 | new_subpart->flags |= PF_POWERUP_LOCK; | ||
| 69 | partdef += 2; | ||
| 70 | } | ||
| 71 | |||
| 72 | *subpart = new_subpart; | ||
| 73 | return 0; | ||
| 74 | fail: | ||
| 75 | kfree(new_subpart); | ||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | static void free_subpart(struct cmdline_parts *parts) | ||
| 80 | { | ||
| 81 | struct cmdline_subpart *subpart; | ||
| 82 | |||
| 83 | while (parts->subpart) { | ||
| 84 | subpart = parts->subpart; | ||
| 85 | parts->subpart = subpart->next_subpart; | ||
| 86 | kfree(subpart); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | static int parse_parts(struct cmdline_parts **parts, const char *bdevdef) | ||
| 91 | { | ||
| 92 | int ret = -EINVAL; | ||
| 93 | char *next; | ||
| 94 | int length; | ||
| 95 | struct cmdline_subpart **next_subpart; | ||
| 96 | struct cmdline_parts *newparts; | ||
| 97 | char buf[BDEVNAME_SIZE + 32 + 4]; | ||
| 98 | |||
| 99 | *parts = NULL; | ||
| 100 | |||
| 101 | newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL); | ||
| 102 | if (!newparts) | ||
| 103 | return -ENOMEM; | ||
| 104 | |||
| 105 | next = strchr(bdevdef, ':'); | ||
| 106 | if (!next) { | ||
| 107 | pr_warn("cmdline partition has no block device."); | ||
| 108 | goto fail; | ||
| 109 | } | ||
| 110 | |||
| 111 | length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1); | ||
| 112 | strncpy(newparts->name, bdevdef, length); | ||
| 113 | newparts->name[length] = '\0'; | ||
| 114 | newparts->nr_subparts = 0; | ||
| 115 | |||
| 116 | next_subpart = &newparts->subpart; | ||
| 117 | |||
| 118 | while (next && *(++next)) { | ||
| 119 | bdevdef = next; | ||
| 120 | next = strchr(bdevdef, ','); | ||
| 121 | |||
| 122 | length = (!next) ? (sizeof(buf) - 1) : | ||
| 123 | min_t(int, next - bdevdef, sizeof(buf) - 1); | ||
| 124 | |||
| 125 | strncpy(buf, bdevdef, length); | ||
| 126 | buf[length] = '\0'; | ||
| 127 | |||
| 128 | ret = parse_subpart(next_subpart, buf); | ||
| 129 | if (ret) | ||
| 130 | goto fail; | ||
| 131 | |||
| 132 | newparts->nr_subparts++; | ||
| 133 | next_subpart = &(*next_subpart)->next_subpart; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (!newparts->subpart) { | ||
| 137 | pr_warn("cmdline partition has no valid partition."); | ||
| 138 | ret = -EINVAL; | ||
| 139 | goto fail; | ||
| 140 | } | ||
| 141 | |||
| 142 | *parts = newparts; | ||
| 143 | |||
| 144 | return 0; | ||
| 145 | fail: | ||
| 146 | free_subpart(newparts); | ||
| 147 | kfree(newparts); | ||
| 148 | return ret; | ||
| 149 | } | ||
| 150 | |||
| 151 | void cmdline_parts_free(struct cmdline_parts **parts) | ||
| 152 | { | ||
| 153 | struct cmdline_parts *next_parts; | ||
| 154 | |||
| 155 | while (*parts) { | ||
| 156 | next_parts = (*parts)->next_parts; | ||
| 157 | free_subpart(*parts); | ||
| 158 | kfree(*parts); | ||
| 159 | *parts = next_parts; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | int cmdline_parts_parse(struct cmdline_parts **parts, const char *cmdline) | ||
| 164 | { | ||
| 165 | int ret; | ||
| 166 | char *buf; | ||
| 167 | char *pbuf; | ||
| 168 | char *next; | ||
| 169 | struct cmdline_parts **next_parts; | ||
| 170 | |||
| 171 | *parts = NULL; | ||
| 172 | |||
| 173 | next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL); | ||
| 174 | if (!buf) | ||
| 175 | return -ENOMEM; | ||
| 176 | |||
| 177 | next_parts = parts; | ||
| 178 | |||
| 179 | while (next && *pbuf) { | ||
| 180 | next = strchr(pbuf, ';'); | ||
| 181 | if (next) | ||
| 182 | *next = '\0'; | ||
| 183 | |||
| 184 | ret = parse_parts(next_parts, pbuf); | ||
| 185 | if (ret) | ||
| 186 | goto fail; | ||
| 187 | |||
| 188 | if (next) | ||
| 189 | pbuf = ++next; | ||
| 190 | |||
| 191 | next_parts = &(*next_parts)->next_parts; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (!*parts) { | ||
| 195 | pr_warn("cmdline partition has no valid partition."); | ||
| 196 | ret = -EINVAL; | ||
| 197 | goto fail; | ||
| 198 | } | ||
| 199 | |||
| 200 | ret = 0; | ||
| 201 | done: | ||
| 202 | kfree(buf); | ||
| 203 | return ret; | ||
| 204 | |||
| 205 | fail: | ||
| 206 | cmdline_parts_free(parts); | ||
| 207 | goto done; | ||
| 208 | } | ||
| 209 | |||
| 210 | struct cmdline_parts *cmdline_parts_find(struct cmdline_parts *parts, | ||
| 211 | const char *bdev) | ||
| 212 | { | ||
| 213 | while (parts && strncmp(bdev, parts->name, sizeof(parts->name))) | ||
| 214 | parts = parts->next_parts; | ||
| 215 | return parts; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * add_part() | ||
| 220 | * 0 success. | ||
| 221 | * 1 can not add so many partitions. | ||
| 222 | */ | ||
| 223 | void cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size, | ||
| 224 | int slot, | ||
| 225 | int (*add_part)(int, struct cmdline_subpart *, void *), | ||
| 226 | void *param) | ||
| 227 | |||
| 228 | { | ||
| 229 | sector_t from = 0; | ||
| 230 | struct cmdline_subpart *subpart; | ||
| 231 | |||
| 232 | for (subpart = parts->subpart; subpart; | ||
| 233 | subpart = subpart->next_subpart, slot++) { | ||
| 234 | if (subpart->from == (sector_t)(~0ULL)) | ||
| 235 | subpart->from = from; | ||
| 236 | else | ||
| 237 | from = subpart->from; | ||
| 238 | |||
| 239 | if (from >= disk_size) | ||
| 240 | break; | ||
| 241 | |||
| 242 | if (subpart->size > (disk_size - from)) | ||
| 243 | subpart->size = disk_size - from; | ||
| 244 | |||
| 245 | from += subpart->size; | ||
| 246 | |||
| 247 | if (add_part(slot, subpart, param)) | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | } | ||
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 7e5d474dc6ba..fbd5a67cb773 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
| @@ -70,7 +70,7 @@ static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, | |||
| 70 | return ret; | 70 | return ret; |
| 71 | 71 | ||
| 72 | ret = copy_to_user(ugeo, &geo, 4); | 72 | ret = copy_to_user(ugeo, &geo, 4); |
| 73 | ret |= __put_user(geo.start, &ugeo->start); | 73 | ret |= put_user(geo.start, &ugeo->start); |
| 74 | if (ret) | 74 | if (ret) |
| 75 | ret = -EFAULT; | 75 | ret = -EFAULT; |
| 76 | 76 | ||
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 20614a332362..9ef66406c625 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c | |||
| @@ -346,7 +346,7 @@ static int deadline_init_queue(struct request_queue *q, struct elevator_type *e) | |||
| 346 | if (!eq) | 346 | if (!eq) |
| 347 | return -ENOMEM; | 347 | return -ENOMEM; |
| 348 | 348 | ||
| 349 | dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node); | 349 | dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node); |
| 350 | if (!dd) { | 350 | if (!dd) { |
| 351 | kobject_put(&eq->kobj); | 351 | kobject_put(&eq->kobj); |
| 352 | return -ENOMEM; | 352 | return -ENOMEM; |
diff --git a/block/elevator.c b/block/elevator.c index 668394d18588..2bcbd8cc14d4 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -155,7 +155,7 @@ struct elevator_queue *elevator_alloc(struct request_queue *q, | |||
| 155 | { | 155 | { |
| 156 | struct elevator_queue *eq; | 156 | struct elevator_queue *eq; |
| 157 | 157 | ||
| 158 | eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); | 158 | eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, q->node); |
| 159 | if (unlikely(!eq)) | 159 | if (unlikely(!eq)) |
| 160 | goto err; | 160 | goto err; |
| 161 | 161 | ||
diff --git a/block/genhd.c b/block/genhd.c index dadf42b454a3..791f41943132 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -1252,8 +1252,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id) | |||
| 1252 | { | 1252 | { |
| 1253 | struct gendisk *disk; | 1253 | struct gendisk *disk; |
| 1254 | 1254 | ||
| 1255 | disk = kmalloc_node(sizeof(struct gendisk), | 1255 | disk = kzalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id); |
| 1256 | GFP_KERNEL | __GFP_ZERO, node_id); | ||
| 1257 | if (disk) { | 1256 | if (disk) { |
| 1258 | if (!init_part_stats(&disk->part0)) { | 1257 | if (!init_part_stats(&disk->part0)) { |
| 1259 | kfree(disk); | 1258 | kfree(disk); |
diff --git a/block/partitions/Kconfig b/block/partitions/Kconfig index 4cebb2f0d2f4..9b29a996c311 100644 --- a/block/partitions/Kconfig +++ b/block/partitions/Kconfig | |||
| @@ -260,3 +260,10 @@ config SYSV68_PARTITION | |||
| 260 | partition table format used by Motorola Delta machines (using | 260 | partition table format used by Motorola Delta machines (using |
| 261 | sysv68). | 261 | sysv68). |
| 262 | Otherwise, say N. | 262 | Otherwise, say N. |
| 263 | |||
| 264 | config CMDLINE_PARTITION | ||
| 265 | bool "Command line partition support" if PARTITION_ADVANCED | ||
| 266 | select BLK_CMDLINE_PARSER | ||
| 267 | help | ||
| 268 | Say Y here if you want to read the partition table from bootargs. | ||
| 269 | The format for the command line is just like mtdparts. | ||
diff --git a/block/partitions/Makefile b/block/partitions/Makefile index 2be4d7ba4e3a..37a95270503c 100644 --- a/block/partitions/Makefile +++ b/block/partitions/Makefile | |||
| @@ -8,6 +8,7 @@ obj-$(CONFIG_ACORN_PARTITION) += acorn.o | |||
| 8 | obj-$(CONFIG_AMIGA_PARTITION) += amiga.o | 8 | obj-$(CONFIG_AMIGA_PARTITION) += amiga.o |
| 9 | obj-$(CONFIG_ATARI_PARTITION) += atari.o | 9 | obj-$(CONFIG_ATARI_PARTITION) += atari.o |
| 10 | obj-$(CONFIG_AIX_PARTITION) += aix.o | 10 | obj-$(CONFIG_AIX_PARTITION) += aix.o |
| 11 | obj-$(CONFIG_CMDLINE_PARTITION) += cmdline.o | ||
| 11 | obj-$(CONFIG_MAC_PARTITION) += mac.o | 12 | obj-$(CONFIG_MAC_PARTITION) += mac.o |
| 12 | obj-$(CONFIG_LDM_PARTITION) += ldm.o | 13 | obj-$(CONFIG_LDM_PARTITION) += ldm.o |
| 13 | obj-$(CONFIG_MSDOS_PARTITION) += msdos.o | 14 | obj-$(CONFIG_MSDOS_PARTITION) += msdos.o |
diff --git a/block/partitions/check.c b/block/partitions/check.c index 19ba207ea7d1..9ac1df74f699 100644 --- a/block/partitions/check.c +++ b/block/partitions/check.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "efi.h" | 34 | #include "efi.h" |
| 35 | #include "karma.h" | 35 | #include "karma.h" |
| 36 | #include "sysv68.h" | 36 | #include "sysv68.h" |
| 37 | #include "cmdline.h" | ||
| 37 | 38 | ||
| 38 | int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ | 39 | int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/ |
| 39 | 40 | ||
| @@ -65,6 +66,9 @@ static int (*check_part[])(struct parsed_partitions *) = { | |||
| 65 | adfspart_check_ADFS, | 66 | adfspart_check_ADFS, |
| 66 | #endif | 67 | #endif |
| 67 | 68 | ||
| 69 | #ifdef CONFIG_CMDLINE_PARTITION | ||
| 70 | cmdline_partition, | ||
| 71 | #endif | ||
| 68 | #ifdef CONFIG_EFI_PARTITION | 72 | #ifdef CONFIG_EFI_PARTITION |
| 69 | efi_partition, /* this must come before msdos */ | 73 | efi_partition, /* this must come before msdos */ |
| 70 | #endif | 74 | #endif |
diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c new file mode 100644 index 000000000000..5141b563adf1 --- /dev/null +++ b/block/partitions/cmdline.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 HUAWEI | ||
| 3 | * Author: Cai Zhiyong <caizhiyong@huawei.com> | ||
| 4 | * | ||
| 5 | * Read block device partition table from the command line. | ||
| 6 | * Typically used for fixed block (eMMC) embedded devices. | ||
| 7 | * It has no MBR, so saves storage space. Bootloader can be easily accessed | ||
| 8 | * by absolute address of data on the block device. | ||
| 9 | * Users can easily change the partition. | ||
| 10 | * | ||
| 11 | * The format for the command line is just like mtdparts. | ||
| 12 | * | ||
| 13 | * For further information, see "Documentation/block/cmdline-partition.txt" | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/cmdline-parser.h> | ||
| 18 | |||
| 19 | #include "check.h" | ||
| 20 | #include "cmdline.h" | ||
| 21 | |||
| 22 | static char *cmdline; | ||
| 23 | static struct cmdline_parts *bdev_parts; | ||
| 24 | |||
| 25 | static int add_part(int slot, struct cmdline_subpart *subpart, void *param) | ||
| 26 | { | ||
| 27 | int label_min; | ||
| 28 | struct partition_meta_info *info; | ||
| 29 | char tmp[sizeof(info->volname) + 4]; | ||
| 30 | struct parsed_partitions *state = (struct parsed_partitions *)param; | ||
| 31 | |||
| 32 | if (slot >= state->limit) | ||
| 33 | return 1; | ||
| 34 | |||
| 35 | put_partition(state, slot, subpart->from >> 9, | ||
| 36 | subpart->size >> 9); | ||
| 37 | |||
| 38 | info = &state->parts[slot].info; | ||
| 39 | |||
| 40 | label_min = min_t(int, sizeof(info->volname) - 1, | ||
| 41 | sizeof(subpart->name)); | ||
| 42 | strncpy(info->volname, subpart->name, label_min); | ||
| 43 | info->volname[label_min] = '\0'; | ||
| 44 | |||
| 45 | snprintf(tmp, sizeof(tmp), "(%s)", info->volname); | ||
| 46 | strlcat(state->pp_buf, tmp, PAGE_SIZE); | ||
| 47 | |||
| 48 | state->parts[slot].has_info = true; | ||
| 49 | |||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int __init cmdline_parts_setup(char *s) | ||
| 54 | { | ||
| 55 | cmdline = s; | ||
| 56 | return 1; | ||
| 57 | } | ||
| 58 | __setup("blkdevparts=", cmdline_parts_setup); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Purpose: allocate cmdline partitions. | ||
| 62 | * Returns: | ||
| 63 | * -1 if unable to read the partition table | ||
| 64 | * 0 if this isn't our partition table | ||
| 65 | * 1 if successful | ||
| 66 | */ | ||
| 67 | int cmdline_partition(struct parsed_partitions *state) | ||
| 68 | { | ||
| 69 | sector_t disk_size; | ||
| 70 | char bdev[BDEVNAME_SIZE]; | ||
| 71 | struct cmdline_parts *parts; | ||
| 72 | |||
| 73 | if (cmdline) { | ||
| 74 | if (bdev_parts) | ||
| 75 | cmdline_parts_free(&bdev_parts); | ||
| 76 | |||
| 77 | if (cmdline_parts_parse(&bdev_parts, cmdline)) { | ||
| 78 | cmdline = NULL; | ||
| 79 | return -1; | ||
| 80 | } | ||
| 81 | cmdline = NULL; | ||
| 82 | } | ||
| 83 | |||
| 84 | if (!bdev_parts) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | bdevname(state->bdev, bdev); | ||
| 88 | parts = cmdline_parts_find(bdev_parts, bdev); | ||
| 89 | if (!parts) | ||
| 90 | return 0; | ||
| 91 | |||
| 92 | disk_size = get_capacity(state->bdev->bd_disk) << 9; | ||
| 93 | |||
| 94 | cmdline_parts_set(parts, disk_size, 1, add_part, (void *)state); | ||
| 95 | |||
| 96 | strlcat(state->pp_buf, "\n", PAGE_SIZE); | ||
| 97 | |||
| 98 | return 1; | ||
| 99 | } | ||
diff --git a/block/partitions/cmdline.h b/block/partitions/cmdline.h new file mode 100644 index 000000000000..26e0f8da1414 --- /dev/null +++ b/block/partitions/cmdline.h | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | |||
| 2 | int cmdline_partition(struct parsed_partitions *state); | ||
diff --git a/block/partitions/efi.c b/block/partitions/efi.c index c85fc895ecdb..a8287b49d062 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | * TODO: | 25 | * TODO: |
| 26 | * | 26 | * |
| 27 | * Changelog: | 27 | * Changelog: |
| 28 | * Mon August 5th, 2013 Davidlohr Bueso <davidlohr@hp.com> | ||
| 29 | * - detect hybrid MBRs, tighter pMBR checking & cleanups. | ||
| 30 | * | ||
| 28 | * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com> | 31 | * Mon Nov 09 2004 Matt Domsch <Matt_Domsch@dell.com> |
| 29 | * - test for valid PMBR and valid PGPT before ever reading | 32 | * - test for valid PMBR and valid PGPT before ever reading |
| 30 | * AGPT, allow override with 'gpt' kernel command line option. | 33 | * AGPT, allow override with 'gpt' kernel command line option. |
| @@ -149,34 +152,89 @@ static u64 last_lba(struct block_device *bdev) | |||
| 149 | bdev_logical_block_size(bdev)) - 1ULL; | 152 | bdev_logical_block_size(bdev)) - 1ULL; |
| 150 | } | 153 | } |
| 151 | 154 | ||
| 152 | static inline int | 155 | static inline int pmbr_part_valid(gpt_mbr_record *part) |
| 153 | pmbr_part_valid(struct partition *part) | ||
| 154 | { | 156 | { |
| 155 | if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT && | 157 | if (part->os_type != EFI_PMBR_OSTYPE_EFI_GPT) |
| 156 | le32_to_cpu(part->start_sect) == 1UL) | 158 | goto invalid; |
| 157 | return 1; | 159 | |
| 158 | return 0; | 160 | /* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */ |
| 161 | if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) | ||
| 162 | goto invalid; | ||
| 163 | |||
| 164 | return GPT_MBR_PROTECTIVE; | ||
| 165 | invalid: | ||
| 166 | return 0; | ||
| 159 | } | 167 | } |
| 160 | 168 | ||
| 161 | /** | 169 | /** |
| 162 | * is_pmbr_valid(): test Protective MBR for validity | 170 | * is_pmbr_valid(): test Protective MBR for validity |
| 163 | * @mbr: pointer to a legacy mbr structure | 171 | * @mbr: pointer to a legacy mbr structure |
| 172 | * @total_sectors: amount of sectors in the device | ||
| 164 | * | 173 | * |
| 165 | * Description: Returns 1 if PMBR is valid, 0 otherwise. | 174 | * Description: Checks for a valid protective or hybrid |
| 166 | * Validity depends on two things: | 175 | * master boot record (MBR). The validity of a pMBR depends |
| 176 | * on all of the following properties: | ||
| 167 | * 1) MSDOS signature is in the last two bytes of the MBR | 177 | * 1) MSDOS signature is in the last two bytes of the MBR |
| 168 | * 2) One partition of type 0xEE is found | 178 | * 2) One partition of type 0xEE is found |
| 179 | * | ||
| 180 | * In addition, a hybrid MBR will have up to three additional | ||
| 181 | * primary partitions, which point to the same space that's | ||
| 182 | * marked out by up to three GPT partitions. | ||
| 183 | * | ||
| 184 | * Returns 0 upon invalid MBR, or GPT_MBR_PROTECTIVE or | ||
| 185 | * GPT_MBR_HYBRID depending on the device layout. | ||
| 169 | */ | 186 | */ |
| 170 | static int | 187 | static int is_pmbr_valid(legacy_mbr *mbr, sector_t total_sectors) |
| 171 | is_pmbr_valid(legacy_mbr *mbr) | ||
| 172 | { | 188 | { |
| 173 | int i; | 189 | uint32_t sz = 0; |
| 190 | int i, part = 0, ret = 0; /* invalid by default */ | ||
| 191 | |||
| 174 | if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) | 192 | if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE) |
| 175 | return 0; | 193 | goto done; |
| 194 | |||
| 195 | for (i = 0; i < 4; i++) { | ||
| 196 | ret = pmbr_part_valid(&mbr->partition_record[i]); | ||
| 197 | if (ret == GPT_MBR_PROTECTIVE) { | ||
| 198 | part = i; | ||
| 199 | /* | ||
| 200 | * Ok, we at least know that there's a protective MBR, | ||
| 201 | * now check if there are other partition types for | ||
| 202 | * hybrid MBR. | ||
| 203 | */ | ||
| 204 | goto check_hybrid; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | if (ret != GPT_MBR_PROTECTIVE) | ||
| 209 | goto done; | ||
| 210 | check_hybrid: | ||
| 176 | for (i = 0; i < 4; i++) | 211 | for (i = 0; i < 4; i++) |
| 177 | if (pmbr_part_valid(&mbr->partition_record[i])) | 212 | if ((mbr->partition_record[i].os_type != |
| 178 | return 1; | 213 | EFI_PMBR_OSTYPE_EFI_GPT) && |
| 179 | return 0; | 214 | (mbr->partition_record[i].os_type != 0x00)) |
| 215 | ret = GPT_MBR_HYBRID; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Protective MBRs take up the lesser of the whole disk | ||
| 219 | * or 2 TiB (32bit LBA), ignoring the rest of the disk. | ||
| 220 | * Some partitioning programs, nonetheless, choose to set | ||
| 221 | * the size to the maximum 32-bit limitation, disregarding | ||
| 222 | * the disk size. | ||
| 223 | * | ||
| 224 | * Hybrid MBRs do not necessarily comply with this. | ||
| 225 | * | ||
| 226 | * Consider a bad value here to be a warning to support dd'ing | ||
| 227 | * an image from a smaller disk to a larger disk. | ||
| 228 | */ | ||
| 229 | if (ret == GPT_MBR_PROTECTIVE) { | ||
| 230 | sz = le32_to_cpu(mbr->partition_record[part].size_in_lba); | ||
| 231 | if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF) | ||
| 232 | pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n", | ||
| 233 | sz, min_t(uint32_t, | ||
| 234 | total_sectors - 1, 0xFFFFFFFF)); | ||
| 235 | } | ||
| 236 | done: | ||
| 237 | return ret; | ||
| 180 | } | 238 | } |
| 181 | 239 | ||
| 182 | /** | 240 | /** |
| @@ -243,8 +301,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, | |||
| 243 | return NULL; | 301 | return NULL; |
| 244 | 302 | ||
| 245 | if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), | 303 | if (read_lba(state, le64_to_cpu(gpt->partition_entry_lba), |
| 246 | (u8 *) pte, | 304 | (u8 *) pte, count) < count) { |
| 247 | count) < count) { | ||
| 248 | kfree(pte); | 305 | kfree(pte); |
| 249 | pte=NULL; | 306 | pte=NULL; |
| 250 | return NULL; | 307 | return NULL; |
| @@ -364,7 +421,12 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, | |||
| 364 | (unsigned long long)lastlba); | 421 | (unsigned long long)lastlba); |
| 365 | goto fail; | 422 | goto fail; |
| 366 | } | 423 | } |
| 367 | 424 | if (le64_to_cpu((*gpt)->last_usable_lba) < le64_to_cpu((*gpt)->first_usable_lba)) { | |
| 425 | pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n", | ||
| 426 | (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), | ||
| 427 | (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba)); | ||
| 428 | goto fail; | ||
| 429 | } | ||
| 368 | /* Check that sizeof_partition_entry has the correct value */ | 430 | /* Check that sizeof_partition_entry has the correct value */ |
| 369 | if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { | 431 | if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { |
| 370 | pr_debug("GUID Partitition Entry Size check failed.\n"); | 432 | pr_debug("GUID Partitition Entry Size check failed.\n"); |
| @@ -429,44 +491,42 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) | |||
| 429 | if (!pgpt || !agpt) | 491 | if (!pgpt || !agpt) |
| 430 | return; | 492 | return; |
| 431 | if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) { | 493 | if (le64_to_cpu(pgpt->my_lba) != le64_to_cpu(agpt->alternate_lba)) { |
| 432 | printk(KERN_WARNING | 494 | pr_warn("GPT:Primary header LBA != Alt. header alternate_lba\n"); |
| 433 | "GPT:Primary header LBA != Alt. header alternate_lba\n"); | 495 | pr_warn("GPT:%lld != %lld\n", |
| 434 | printk(KERN_WARNING "GPT:%lld != %lld\n", | ||
| 435 | (unsigned long long)le64_to_cpu(pgpt->my_lba), | 496 | (unsigned long long)le64_to_cpu(pgpt->my_lba), |
| 436 | (unsigned long long)le64_to_cpu(agpt->alternate_lba)); | 497 | (unsigned long long)le64_to_cpu(agpt->alternate_lba)); |
| 437 | error_found++; | 498 | error_found++; |
| 438 | } | 499 | } |
| 439 | if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) { | 500 | if (le64_to_cpu(pgpt->alternate_lba) != le64_to_cpu(agpt->my_lba)) { |
| 440 | printk(KERN_WARNING | 501 | pr_warn("GPT:Primary header alternate_lba != Alt. header my_lba\n"); |
| 441 | "GPT:Primary header alternate_lba != Alt. header my_lba\n"); | 502 | pr_warn("GPT:%lld != %lld\n", |
| 442 | printk(KERN_WARNING "GPT:%lld != %lld\n", | ||
| 443 | (unsigned long long)le64_to_cpu(pgpt->alternate_lba), | 503 | (unsigned long long)le64_to_cpu(pgpt->alternate_lba), |
| 444 | (unsigned long long)le64_to_cpu(agpt->my_lba)); | 504 | (unsigned long long)le64_to_cpu(agpt->my_lba)); |
| 445 | error_found++; | 505 | error_found++; |
| 446 | } | 506 | } |
| 447 | if (le64_to_cpu(pgpt->first_usable_lba) != | 507 | if (le64_to_cpu(pgpt->first_usable_lba) != |
| 448 | le64_to_cpu(agpt->first_usable_lba)) { | 508 | le64_to_cpu(agpt->first_usable_lba)) { |
| 449 | printk(KERN_WARNING "GPT:first_usable_lbas don't match.\n"); | 509 | pr_warn("GPT:first_usable_lbas don't match.\n"); |
| 450 | printk(KERN_WARNING "GPT:%lld != %lld\n", | 510 | pr_warn("GPT:%lld != %lld\n", |
| 451 | (unsigned long long)le64_to_cpu(pgpt->first_usable_lba), | 511 | (unsigned long long)le64_to_cpu(pgpt->first_usable_lba), |
| 452 | (unsigned long long)le64_to_cpu(agpt->first_usable_lba)); | 512 | (unsigned long long)le64_to_cpu(agpt->first_usable_lba)); |
| 453 | error_found++; | 513 | error_found++; |
| 454 | } | 514 | } |
| 455 | if (le64_to_cpu(pgpt->last_usable_lba) != | 515 | if (le64_to_cpu(pgpt->last_usable_lba) != |
| 456 | le64_to_cpu(agpt->last_usable_lba)) { | 516 | le64_to_cpu(agpt->last_usable_lba)) { |
| 457 | printk(KERN_WARNING "GPT:last_usable_lbas don't match.\n"); | 517 | pr_warn("GPT:last_usable_lbas don't match.\n"); |
| 458 | printk(KERN_WARNING "GPT:%lld != %lld\n", | 518 | pr_warn("GPT:%lld != %lld\n", |
| 459 | (unsigned long long)le64_to_cpu(pgpt->last_usable_lba), | 519 | (unsigned long long)le64_to_cpu(pgpt->last_usable_lba), |
| 460 | (unsigned long long)le64_to_cpu(agpt->last_usable_lba)); | 520 | (unsigned long long)le64_to_cpu(agpt->last_usable_lba)); |
| 461 | error_found++; | 521 | error_found++; |
| 462 | } | 522 | } |
| 463 | if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) { | 523 | if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) { |
| 464 | printk(KERN_WARNING "GPT:disk_guids don't match.\n"); | 524 | pr_warn("GPT:disk_guids don't match.\n"); |
| 465 | error_found++; | 525 | error_found++; |
| 466 | } | 526 | } |
| 467 | if (le32_to_cpu(pgpt->num_partition_entries) != | 527 | if (le32_to_cpu(pgpt->num_partition_entries) != |
| 468 | le32_to_cpu(agpt->num_partition_entries)) { | 528 | le32_to_cpu(agpt->num_partition_entries)) { |
| 469 | printk(KERN_WARNING "GPT:num_partition_entries don't match: " | 529 | pr_warn("GPT:num_partition_entries don't match: " |
| 470 | "0x%x != 0x%x\n", | 530 | "0x%x != 0x%x\n", |
| 471 | le32_to_cpu(pgpt->num_partition_entries), | 531 | le32_to_cpu(pgpt->num_partition_entries), |
| 472 | le32_to_cpu(agpt->num_partition_entries)); | 532 | le32_to_cpu(agpt->num_partition_entries)); |
| @@ -474,8 +534,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) | |||
| 474 | } | 534 | } |
| 475 | if (le32_to_cpu(pgpt->sizeof_partition_entry) != | 535 | if (le32_to_cpu(pgpt->sizeof_partition_entry) != |
| 476 | le32_to_cpu(agpt->sizeof_partition_entry)) { | 536 | le32_to_cpu(agpt->sizeof_partition_entry)) { |
| 477 | printk(KERN_WARNING | 537 | pr_warn("GPT:sizeof_partition_entry values don't match: " |
| 478 | "GPT:sizeof_partition_entry values don't match: " | ||
| 479 | "0x%x != 0x%x\n", | 538 | "0x%x != 0x%x\n", |
| 480 | le32_to_cpu(pgpt->sizeof_partition_entry), | 539 | le32_to_cpu(pgpt->sizeof_partition_entry), |
| 481 | le32_to_cpu(agpt->sizeof_partition_entry)); | 540 | le32_to_cpu(agpt->sizeof_partition_entry)); |
| @@ -483,34 +542,30 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, u64 lastlba) | |||
| 483 | } | 542 | } |
| 484 | if (le32_to_cpu(pgpt->partition_entry_array_crc32) != | 543 | if (le32_to_cpu(pgpt->partition_entry_array_crc32) != |
| 485 | le32_to_cpu(agpt->partition_entry_array_crc32)) { | 544 | le32_to_cpu(agpt->partition_entry_array_crc32)) { |
| 486 | printk(KERN_WARNING | 545 | pr_warn("GPT:partition_entry_array_crc32 values don't match: " |
| 487 | "GPT:partition_entry_array_crc32 values don't match: " | ||
| 488 | "0x%x != 0x%x\n", | 546 | "0x%x != 0x%x\n", |
| 489 | le32_to_cpu(pgpt->partition_entry_array_crc32), | 547 | le32_to_cpu(pgpt->partition_entry_array_crc32), |
| 490 | le32_to_cpu(agpt->partition_entry_array_crc32)); | 548 | le32_to_cpu(agpt->partition_entry_array_crc32)); |
| 491 | error_found++; | 549 | error_found++; |
| 492 | } | 550 | } |
| 493 | if (le64_to_cpu(pgpt->alternate_lba) != lastlba) { | 551 | if (le64_to_cpu(pgpt->alternate_lba) != lastlba) { |
| 494 | printk(KERN_WARNING | 552 | pr_warn("GPT:Primary header thinks Alt. header is not at the end of the disk.\n"); |
| 495 | "GPT:Primary header thinks Alt. header is not at the end of the disk.\n"); | 553 | pr_warn("GPT:%lld != %lld\n", |
| 496 | printk(KERN_WARNING "GPT:%lld != %lld\n", | ||
| 497 | (unsigned long long)le64_to_cpu(pgpt->alternate_lba), | 554 | (unsigned long long)le64_to_cpu(pgpt->alternate_lba), |
| 498 | (unsigned long long)lastlba); | 555 | (unsigned long long)lastlba); |
| 499 | error_found++; | 556 | error_found++; |
| 500 | } | 557 | } |
| 501 | 558 | ||
| 502 | if (le64_to_cpu(agpt->my_lba) != lastlba) { | 559 | if (le64_to_cpu(agpt->my_lba) != lastlba) { |
| 503 | printk(KERN_WARNING | 560 | pr_warn("GPT:Alternate GPT header not at the end of the disk.\n"); |
| 504 | "GPT:Alternate GPT header not at the end of the disk.\n"); | 561 | pr_warn("GPT:%lld != %lld\n", |
| 505 | printk(KERN_WARNING "GPT:%lld != %lld\n", | ||
| 506 | (unsigned long long)le64_to_cpu(agpt->my_lba), | 562 | (unsigned long long)le64_to_cpu(agpt->my_lba), |
| 507 | (unsigned long long)lastlba); | 563 | (unsigned long long)lastlba); |
| 508 | error_found++; | 564 | error_found++; |
| 509 | } | 565 | } |
| 510 | 566 | ||
| 511 | if (error_found) | 567 | if (error_found) |
| 512 | printk(KERN_WARNING | 568 | pr_warn("GPT: Use GNU Parted to correct GPT errors.\n"); |
| 513 | "GPT: Use GNU Parted to correct GPT errors.\n"); | ||
| 514 | return; | 569 | return; |
| 515 | } | 570 | } |
| 516 | 571 | ||
| @@ -536,6 +591,7 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, | |||
| 536 | gpt_header *pgpt = NULL, *agpt = NULL; | 591 | gpt_header *pgpt = NULL, *agpt = NULL; |
| 537 | gpt_entry *pptes = NULL, *aptes = NULL; | 592 | gpt_entry *pptes = NULL, *aptes = NULL; |
| 538 | legacy_mbr *legacymbr; | 593 | legacy_mbr *legacymbr; |
| 594 | sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9; | ||
| 539 | u64 lastlba; | 595 | u64 lastlba; |
| 540 | 596 | ||
| 541 | if (!ptes) | 597 | if (!ptes) |
| @@ -543,17 +599,22 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, | |||
| 543 | 599 | ||
| 544 | lastlba = last_lba(state->bdev); | 600 | lastlba = last_lba(state->bdev); |
| 545 | if (!force_gpt) { | 601 | if (!force_gpt) { |
| 546 | /* This will be added to the EFI Spec. per Intel after v1.02. */ | 602 | /* This will be added to the EFI Spec. per Intel after v1.02. */ |
| 547 | legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); | 603 | legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL); |
| 548 | if (legacymbr) { | 604 | if (!legacymbr) |
| 549 | read_lba(state, 0, (u8 *) legacymbr, | 605 | goto fail; |
| 550 | sizeof (*legacymbr)); | 606 | |
| 551 | good_pmbr = is_pmbr_valid(legacymbr); | 607 | read_lba(state, 0, (u8 *)legacymbr, sizeof(*legacymbr)); |
| 552 | kfree(legacymbr); | 608 | good_pmbr = is_pmbr_valid(legacymbr, total_sectors); |
| 553 | } | 609 | kfree(legacymbr); |
| 554 | if (!good_pmbr) | 610 | |
| 555 | goto fail; | 611 | if (!good_pmbr) |
| 556 | } | 612 | goto fail; |
| 613 | |||
| 614 | pr_debug("Device has a %s MBR\n", | ||
| 615 | good_pmbr == GPT_MBR_PROTECTIVE ? | ||
| 616 | "protective" : "hybrid"); | ||
| 617 | } | ||
| 557 | 618 | ||
| 558 | good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, | 619 | good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, |
| 559 | &pgpt, &pptes); | 620 | &pgpt, &pptes); |
| @@ -576,11 +637,8 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, | |||
| 576 | *ptes = pptes; | 637 | *ptes = pptes; |
| 577 | kfree(agpt); | 638 | kfree(agpt); |
| 578 | kfree(aptes); | 639 | kfree(aptes); |
| 579 | if (!good_agpt) { | 640 | if (!good_agpt) |
| 580 | printk(KERN_WARNING | 641 | pr_warn("Alternate GPT is invalid, using primary GPT.\n"); |
| 581 | "Alternate GPT is invalid, " | ||
| 582 | "using primary GPT.\n"); | ||
| 583 | } | ||
| 584 | return 1; | 642 | return 1; |
| 585 | } | 643 | } |
| 586 | else if (good_agpt) { | 644 | else if (good_agpt) { |
| @@ -588,8 +646,7 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, | |||
| 588 | *ptes = aptes; | 646 | *ptes = aptes; |
| 589 | kfree(pgpt); | 647 | kfree(pgpt); |
| 590 | kfree(pptes); | 648 | kfree(pptes); |
| 591 | printk(KERN_WARNING | 649 | pr_warn("Primary GPT is invalid, using alternate GPT.\n"); |
| 592 | "Primary GPT is invalid, using alternate GPT.\n"); | ||
| 593 | return 1; | 650 | return 1; |
| 594 | } | 651 | } |
| 595 | 652 | ||
| @@ -651,8 +708,7 @@ int efi_partition(struct parsed_partitions *state) | |||
| 651 | put_partition(state, i+1, start * ssz, size * ssz); | 708 | put_partition(state, i+1, start * ssz, size * ssz); |
| 652 | 709 | ||
| 653 | /* If this is a RAID volume, tell md */ | 710 | /* If this is a RAID volume, tell md */ |
| 654 | if (!efi_guidcmp(ptes[i].partition_type_guid, | 711 | if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) |
| 655 | PARTITION_LINUX_RAID_GUID)) | ||
| 656 | state->parts[i + 1].flags = ADDPART_FLAG_RAID; | 712 | state->parts[i + 1].flags = ADDPART_FLAG_RAID; |
| 657 | 713 | ||
| 658 | info = &state->parts[i + 1].info; | 714 | info = &state->parts[i + 1].info; |
diff --git a/block/partitions/efi.h b/block/partitions/efi.h index b69ab729558f..4efcafba7e64 100644 --- a/block/partitions/efi.h +++ b/block/partitions/efi.h | |||
| @@ -37,6 +37,9 @@ | |||
| 37 | #define EFI_PMBR_OSTYPE_EFI 0xEF | 37 | #define EFI_PMBR_OSTYPE_EFI 0xEF |
| 38 | #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE | 38 | #define EFI_PMBR_OSTYPE_EFI_GPT 0xEE |
| 39 | 39 | ||
| 40 | #define GPT_MBR_PROTECTIVE 1 | ||
| 41 | #define GPT_MBR_HYBRID 2 | ||
| 42 | |||
| 40 | #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL | 43 | #define GPT_HEADER_SIGNATURE 0x5452415020494645ULL |
| 41 | #define GPT_HEADER_REVISION_V1 0x00010000 | 44 | #define GPT_HEADER_REVISION_V1 0x00010000 |
| 42 | #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 | 45 | #define GPT_PRIMARY_PARTITION_TABLE_LBA 1 |
| @@ -101,11 +104,25 @@ typedef struct _gpt_entry { | |||
| 101 | efi_char16_t partition_name[72 / sizeof (efi_char16_t)]; | 104 | efi_char16_t partition_name[72 / sizeof (efi_char16_t)]; |
| 102 | } __attribute__ ((packed)) gpt_entry; | 105 | } __attribute__ ((packed)) gpt_entry; |
| 103 | 106 | ||
| 107 | typedef struct _gpt_mbr_record { | ||
| 108 | u8 boot_indicator; /* unused by EFI, set to 0x80 for bootable */ | ||
| 109 | u8 start_head; /* unused by EFI, pt start in CHS */ | ||
| 110 | u8 start_sector; /* unused by EFI, pt start in CHS */ | ||
| 111 | u8 start_track; | ||
| 112 | u8 os_type; /* EFI and legacy non-EFI OS types */ | ||
| 113 | u8 end_head; /* unused by EFI, pt end in CHS */ | ||
| 114 | u8 end_sector; /* unused by EFI, pt end in CHS */ | ||
| 115 | u8 end_track; /* unused by EFI, pt end in CHS */ | ||
| 116 | __le32 starting_lba; /* used by EFI - start addr of the on disk pt */ | ||
| 117 | __le32 size_in_lba; /* used by EFI - size of pt in LBA */ | ||
| 118 | } __packed gpt_mbr_record; | ||
| 119 | |||
| 120 | |||
| 104 | typedef struct _legacy_mbr { | 121 | typedef struct _legacy_mbr { |
| 105 | u8 boot_code[440]; | 122 | u8 boot_code[440]; |
| 106 | __le32 unique_mbr_signature; | 123 | __le32 unique_mbr_signature; |
| 107 | __le16 unknown; | 124 | __le16 unknown; |
| 108 | struct partition partition_record[4]; | 125 | gpt_mbr_record partition_record[4]; |
| 109 | __le16 signature; | 126 | __le16 signature; |
| 110 | } __attribute__ ((packed)) legacy_mbr; | 127 | } __attribute__ ((packed)) legacy_mbr; |
| 111 | 128 | ||
| @@ -113,22 +130,3 @@ typedef struct _legacy_mbr { | |||
| 113 | extern int efi_partition(struct parsed_partitions *state); | 130 | extern int efi_partition(struct parsed_partitions *state); |
| 114 | 131 | ||
| 115 | #endif | 132 | #endif |
| 116 | |||
| 117 | /* | ||
| 118 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 119 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 120 | * adjust the settings for this buffer only. This must remain at the end | ||
| 121 | * of the file. | ||
| 122 | * -------------------------------------------------------------------------- | ||
| 123 | * Local variables: | ||
| 124 | * c-indent-level: 4 | ||
| 125 | * c-brace-imaginary-offset: 0 | ||
| 126 | * c-brace-offset: -4 | ||
| 127 | * c-argdecl-indent: 4 | ||
| 128 | * c-label-offset: -4 | ||
| 129 | * c-continued-statement-offset: 4 | ||
| 130 | * c-continued-brace-offset: 0 | ||
| 131 | * indent-tabs-mode: nil | ||
| 132 | * tab-width: 8 | ||
| 133 | * End: | ||
| 134 | */ | ||
