linux/fs/partitions/check.c
<<
>>
Prefs
   1/*
   2 *  fs/partitions/check.c
   3 *
   4 *  Code extracted from drivers/block/genhd.c
   5 *  Copyright (C) 1991-1998  Linus Torvalds
   6 *  Re-organised Feb 1998 Russell King
   7 *
   8 *  We now have independent partition support from the
   9 *  block drivers, which allows all the partition code to
  10 *  be grouped in one location, and it to be mostly self
  11 *  contained.
  12 *
  13 *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
  14 */
  15
  16#include <linux/init.h>
  17#include <linux/module.h>
  18#include <linux/fs.h>
  19#include <linux/kmod.h>
  20#include <linux/ctype.h>
  21#include <linux/genhd.h>
  22
  23#include "check.h"
  24
  25#include "acorn.h"
  26#include "amiga.h"
  27#include "atari.h"
  28#include "ldm.h"
  29#include "mac.h"
  30#include "msdos.h"
  31#include "osf.h"
  32#include "sgi.h"
  33#include "sun.h"
  34#include "ibm.h"
  35#include "ultrix.h"
  36#include "efi.h"
  37#include "karma.h"
  38#include "sysv68.h"
  39
  40#ifdef CONFIG_BLK_DEV_MD
  41extern void md_autodetect_dev(dev_t dev);
  42#endif
  43
  44int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
  45
  46static int (*check_part[])(struct parsed_partitions *, struct block_device *) = {
  47        /*
  48         * Probe partition formats with tables at disk address 0
  49         * that also have an ADFS boot block at 0xdc0.
  50         */
  51#ifdef CONFIG_ACORN_PARTITION_ICS
  52        adfspart_check_ICS,
  53#endif
  54#ifdef CONFIG_ACORN_PARTITION_POWERTEC
  55        adfspart_check_POWERTEC,
  56#endif
  57#ifdef CONFIG_ACORN_PARTITION_EESOX
  58        adfspart_check_EESOX,
  59#endif
  60
  61        /*
  62         * Now move on to formats that only have partition info at
  63         * disk address 0xdc0.  Since these may also have stale
  64         * PC/BIOS partition tables, they need to come before
  65         * the msdos entry.
  66         */
  67#ifdef CONFIG_ACORN_PARTITION_CUMANA
  68        adfspart_check_CUMANA,
  69#endif
  70#ifdef CONFIG_ACORN_PARTITION_ADFS
  71        adfspart_check_ADFS,
  72#endif
  73
  74#ifdef CONFIG_EFI_PARTITION
  75        efi_partition,          /* this must come before msdos */
  76#endif
  77#ifdef CONFIG_SGI_PARTITION
  78        sgi_partition,
  79#endif
  80#ifdef CONFIG_LDM_PARTITION
  81        ldm_partition,          /* this must come before msdos */
  82#endif
  83#ifdef CONFIG_MSDOS_PARTITION
  84        msdos_partition,
  85#endif
  86#ifdef CONFIG_OSF_PARTITION
  87        osf_partition,
  88#endif
  89#ifdef CONFIG_SUN_PARTITION
  90        sun_partition,
  91#endif
  92#ifdef CONFIG_AMIGA_PARTITION
  93        amiga_partition,
  94#endif
  95#ifdef CONFIG_ATARI_PARTITION
  96        atari_partition,
  97#endif
  98#ifdef CONFIG_MAC_PARTITION
  99        mac_partition,
 100#endif
 101#ifdef CONFIG_ULTRIX_PARTITION
 102        ultrix_partition,
 103#endif
 104#ifdef CONFIG_IBM_PARTITION
 105        ibm_partition,
 106#endif
 107#ifdef CONFIG_KARMA_PARTITION
 108        karma_partition,
 109#endif
 110#ifdef CONFIG_SYSV68_PARTITION
 111        sysv68_partition,
 112#endif
 113        NULL
 114};
 115 
 116/*
 117 * disk_name() is used by partition check code and the genhd driver.
 118 * It formats the devicename of the indicated disk into
 119 * the supplied buffer (of size at least 32), and returns
 120 * a pointer to that same buffer (for convenience).
 121 */
 122
 123char *disk_name(struct gendisk *hd, int partno, char *buf)
 124{
 125        if (!partno)
 126                snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name);
 127        else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1]))
 128                snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno);
 129        else
 130                snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno);
 131
 132        return buf;
 133}
 134
 135const char *bdevname(struct block_device *bdev, char *buf)
 136{
 137        return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf);
 138}
 139
 140EXPORT_SYMBOL(bdevname);
 141
 142/*
 143 * There's very little reason to use this, you should really
 144 * have a struct block_device just about everywhere and use
 145 * bdevname() instead.
 146 */
 147const char *__bdevname(dev_t dev, char *buffer)
 148{
 149        scnprintf(buffer, BDEVNAME_SIZE, "unknown-block(%u,%u)",
 150                                MAJOR(dev), MINOR(dev));
 151        return buffer;
 152}
 153
 154EXPORT_SYMBOL(__bdevname);
 155
 156static struct parsed_partitions *
 157check_partition(struct gendisk *hd, struct block_device *bdev)
 158{
 159        struct parsed_partitions *state;
 160        int i, res, err;
 161
 162        state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
 163        if (!state)
 164                return NULL;
 165
 166        disk_name(hd, 0, state->name);
 167        printk(KERN_INFO " %s:", state->name);
 168        if (isdigit(state->name[strlen(state->name)-1]))
 169                sprintf(state->name, "p");
 170
 171        state->limit = disk_max_parts(hd);
 172        i = res = err = 0;
 173        while (!res && check_part[i]) {
 174                memset(&state->parts, 0, sizeof(state->parts));
 175                res = check_part[i++](state, bdev);
 176                if (res < 0) {
 177                        /* We have hit an I/O error which we don't report now.
 178                        * But record it, and let the others do their job.
 179                        */
 180                        err = res;
 181                        res = 0;
 182                }
 183
 184        }
 185        if (res > 0)
 186                return state;
 187        if (err)
 188        /* The partition is unrecognized. So report I/O errors if there were any */
 189                res = err;
 190        if (!res)
 191                printk(" unknown partition table\n");
 192        else if (warn_no_part)
 193                printk(" unable to read partition table\n");
 194        kfree(state);
 195        return ERR_PTR(res);
 196}
 197
 198static ssize_t part_partition_show(struct device *dev,
 199                                   struct device_attribute *attr, char *buf)
 200{
 201        struct hd_struct *p = dev_to_part(dev);
 202
 203        return sprintf(buf, "%d\n", p->partno);
 204}
 205
 206static ssize_t part_start_show(struct device *dev,
 207                               struct device_attribute *attr, char *buf)
 208{
 209        struct hd_struct *p = dev_to_part(dev);
 210
 211        return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect);
 212}
 213
 214ssize_t part_size_show(struct device *dev,
 215                       struct device_attribute *attr, char *buf)
 216{
 217        struct hd_struct *p = dev_to_part(dev);
 218        return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 219}
 220
 221ssize_t part_stat_show(struct device *dev,
 222                       struct device_attribute *attr, char *buf)
 223{
 224        struct hd_struct *p = dev_to_part(dev);
 225        int cpu;
 226
 227        cpu = part_stat_lock();
 228        part_round_stats(cpu, p);
 229        part_stat_unlock();
 230        return sprintf(buf,
 231                "%8lu %8lu %8llu %8u "
 232                "%8lu %8lu %8llu %8u "
 233                "%8u %8u %8u"
 234                "\n",
 235                part_stat_read(p, ios[READ]),
 236                part_stat_read(p, merges[READ]),
 237                (unsigned long long)part_stat_read(p, sectors[READ]),
 238                jiffies_to_msecs(part_stat_read(p, ticks[READ])),
 239                part_stat_read(p, ios[WRITE]),
 240                part_stat_read(p, merges[WRITE]),
 241                (unsigned long long)part_stat_read(p, sectors[WRITE]),
 242                jiffies_to_msecs(part_stat_read(p, ticks[WRITE])),
 243                p->in_flight,
 244                jiffies_to_msecs(part_stat_read(p, io_ticks)),
 245                jiffies_to_msecs(part_stat_read(p, time_in_queue)));
 246}
 247
 248#ifdef CONFIG_FAIL_MAKE_REQUEST
 249ssize_t part_fail_show(struct device *dev,
 250                       struct device_attribute *attr, char *buf)
 251{
 252        struct hd_struct *p = dev_to_part(dev);
 253
 254        return sprintf(buf, "%d\n", p->make_it_fail);
 255}
 256
 257ssize_t part_fail_store(struct device *dev,
 258                        struct device_attribute *attr,
 259                        const char *buf, size_t count)
 260{
 261        struct hd_struct *p = dev_to_part(dev);
 262        int i;
 263
 264        if (count > 0 && sscanf(buf, "%d", &i) > 0)
 265                p->make_it_fail = (i == 0) ? 0 : 1;
 266
 267        return count;
 268}
 269#endif
 270
 271static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL);
 272static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL);
 273static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL);
 274static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL);
 275#ifdef CONFIG_FAIL_MAKE_REQUEST
 276static struct device_attribute dev_attr_fail =
 277        __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store);
 278#endif
 279
 280static struct attribute *part_attrs[] = {
 281        &dev_attr_partition.attr,
 282        &dev_attr_start.attr,
 283        &dev_attr_size.attr,
 284        &dev_attr_stat.attr,
 285#ifdef CONFIG_FAIL_MAKE_REQUEST
 286        &dev_attr_fail.attr,
 287#endif
 288        NULL
 289};
 290
 291static struct attribute_group part_attr_group = {
 292        .attrs = part_attrs,
 293};
 294
 295static struct attribute_group *part_attr_groups[] = {
 296        &part_attr_group,
 297        NULL
 298};
 299
 300static void part_release(struct device *dev)
 301{
 302        struct hd_struct *p = dev_to_part(dev);
 303        free_part_stats(p);
 304        kfree(p);
 305}
 306
 307struct device_type part_type = {
 308        .name           = "partition",
 309        .groups         = part_attr_groups,
 310        .release        = part_release,
 311};
 312
 313static void delete_partition_rcu_cb(struct rcu_head *head)
 314{
 315        struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
 316
 317        part->start_sect = 0;
 318        part->nr_sects = 0;
 319        part_stat_set_all(part, 0);
 320        put_device(part_to_dev(part));
 321}
 322
 323void delete_partition(struct gendisk *disk, int partno)
 324{
 325        struct disk_part_tbl *ptbl = disk->part_tbl;
 326        struct hd_struct *part;
 327
 328        if (partno >= ptbl->len)
 329                return;
 330
 331        part = ptbl->part[partno];
 332        if (!part)
 333                return;
 334
 335        blk_free_devt(part_devt(part));
 336        rcu_assign_pointer(ptbl->part[partno], NULL);
 337        rcu_assign_pointer(ptbl->last_lookup, NULL);
 338        kobject_put(part->holder_dir);
 339        device_del(part_to_dev(part));
 340
 341        call_rcu(&part->rcu_head, delete_partition_rcu_cb);
 342}
 343
 344static ssize_t whole_disk_show(struct device *dev,
 345                               struct device_attribute *attr, char *buf)
 346{
 347        return 0;
 348}
 349static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH,
 350                   whole_disk_show, NULL);
 351
 352struct hd_struct *add_partition(struct gendisk *disk, int partno,
 353                                sector_t start, sector_t len, int flags)
 354{
 355        struct hd_struct *p;
 356        dev_t devt = MKDEV(0, 0);
 357        struct device *ddev = disk_to_dev(disk);
 358        struct device *pdev;
 359        struct disk_part_tbl *ptbl;
 360        const char *dname;
 361        int err;
 362
 363        err = disk_expand_part_tbl(disk, partno);
 364        if (err)
 365                return ERR_PTR(err);
 366        ptbl = disk->part_tbl;
 367
 368        if (ptbl->part[partno])
 369                return ERR_PTR(-EBUSY);
 370
 371        p = kzalloc(sizeof(*p), GFP_KERNEL);
 372        if (!p)
 373                return ERR_PTR(-EBUSY);
 374
 375        if (!init_part_stats(p)) {
 376                err = -ENOMEM;
 377                goto out_free;
 378        }
 379        pdev = part_to_dev(p);
 380
 381        p->start_sect = start;
 382        p->nr_sects = len;
 383        p->partno = partno;
 384        p->policy = get_disk_ro(disk);
 385
 386        dname = dev_name(ddev);
 387        if (isdigit(dname[strlen(dname) - 1]))
 388                dev_set_name(pdev, "%sp%d", dname, partno);
 389        else
 390                dev_set_name(pdev, "%s%d", dname, partno);
 391
 392        device_initialize(pdev);
 393        pdev->class = &block_class;
 394        pdev->type = &part_type;
 395        pdev->parent = ddev;
 396
 397        err = blk_alloc_devt(p, &devt);
 398        if (err)
 399                goto out_free_stats;
 400        pdev->devt = devt;
 401
 402        /* delay uevent until 'holders' subdir is created */
 403        pdev->uevent_suppress = 1;
 404        err = device_add(pdev);
 405        if (err)
 406                goto out_put;
 407
 408        err = -ENOMEM;
 409        p->holder_dir = kobject_create_and_add("holders", &pdev->kobj);
 410        if (!p->holder_dir)
 411                goto out_del;
 412
 413        pdev->uevent_suppress = 0;
 414        if (flags & ADDPART_FLAG_WHOLEDISK) {
 415                err = device_create_file(pdev, &dev_attr_whole_disk);
 416                if (err)
 417                        goto out_del;
 418        }
 419
 420        /* everything is up and running, commence */
 421        INIT_RCU_HEAD(&p->rcu_head);
 422        rcu_assign_pointer(ptbl->part[partno], p);
 423
 424        /* suppress uevent if the disk supresses it */
 425        if (!ddev->uevent_suppress)
 426                kobject_uevent(&pdev->kobj, KOBJ_ADD);
 427
 428        return p;
 429
 430out_free_stats:
 431        free_part_stats(p);
 432out_free:
 433        kfree(p);
 434        return ERR_PTR(err);
 435out_del:
 436        kobject_put(p->holder_dir);
 437        device_del(pdev);
 438out_put:
 439        put_device(pdev);
 440        blk_free_devt(devt);
 441        return ERR_PTR(err);
 442}
 443
 444/* Not exported, helper to add_disk(). */
 445void register_disk(struct gendisk *disk)
 446{
 447        struct device *ddev = disk_to_dev(disk);
 448        struct block_device *bdev;
 449        struct disk_part_iter piter;
 450        struct hd_struct *part;
 451        int err;
 452
 453        ddev->parent = disk->driverfs_dev;
 454
 455        dev_set_name(ddev, disk->disk_name);
 456
 457        /* delay uevents, until we scanned partition table */
 458        ddev->uevent_suppress = 1;
 459
 460        if (device_add(ddev))
 461                return;
 462#ifndef CONFIG_SYSFS_DEPRECATED
 463        err = sysfs_create_link(block_depr, &ddev->kobj,
 464                                kobject_name(&ddev->kobj));
 465        if (err) {
 466                device_del(ddev);
 467                return;
 468        }
 469#endif
 470        disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
 471        disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 472
 473        /* No minors to use for partitions */
 474        if (!disk_partitionable(disk))
 475                goto exit;
 476
 477        /* No such device (e.g., media were just removed) */
 478        if (!get_capacity(disk))
 479                goto exit;
 480
 481        bdev = bdget_disk(disk, 0);
 482        if (!bdev)
 483                goto exit;
 484
 485        bdev->bd_invalidated = 1;
 486        err = blkdev_get(bdev, FMODE_READ);
 487        if (err < 0)
 488                goto exit;
 489        blkdev_put(bdev, FMODE_READ);
 490
 491exit:
 492        /* announce disk after possible partitions are created */
 493        ddev->uevent_suppress = 0;
 494        kobject_uevent(&ddev->kobj, KOBJ_ADD);
 495
 496        /* announce possible partitions */
 497        disk_part_iter_init(&piter, disk, 0);
 498        while ((part = disk_part_iter_next(&piter)))
 499                kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
 500        disk_part_iter_exit(&piter);
 501}
 502
 503int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 504{
 505        struct disk_part_iter piter;
 506        struct hd_struct *part;
 507        struct parsed_partitions *state;
 508        int p, highest, res;
 509
 510        if (bdev->bd_part_count)
 511                return -EBUSY;
 512        res = invalidate_partition(disk, 0);
 513        if (res)
 514                return res;
 515
 516        disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
 517        while ((part = disk_part_iter_next(&piter)))
 518                delete_partition(disk, part->partno);
 519        disk_part_iter_exit(&piter);
 520
 521        if (disk->fops->revalidate_disk)
 522                disk->fops->revalidate_disk(disk);
 523        check_disk_size_change(disk, bdev);
 524        bdev->bd_invalidated = 0;
 525        if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
 526                return 0;
 527        if (IS_ERR(state))      /* I/O error reading the partition table */
 528                return -EIO;
 529
 530        /* tell userspace that the media / partition table may have changed */
 531        kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
 532
 533        /* Detect the highest partition number and preallocate
 534         * disk->part_tbl.  This is an optimization and not strictly
 535         * necessary.
 536         */
 537        for (p = 1, highest = 0; p < state->limit; p++)
 538                if (state->parts[p].size)
 539                        highest = p;
 540
 541        disk_expand_part_tbl(disk, highest);
 542
 543        /* add partitions */
 544        for (p = 1; p < state->limit; p++) {
 545                sector_t size = state->parts[p].size;
 546                sector_t from = state->parts[p].from;
 547                if (!size)
 548                        continue;
 549                if (from >= get_capacity(disk)) {
 550                        printk(KERN_WARNING
 551                               "%s: p%d ignored, start %llu is behind the end of the disk\n",
 552                               disk->disk_name, p, (unsigned long long) from);
 553                        continue;
 554                }
 555                if (from + size > get_capacity(disk)) {
 556                        /*
 557                         * we can not ignore partitions of broken tables
 558                         * created by for example camera firmware, but we
 559                         * limit them to the end of the disk to avoid
 560                         * creating invalid block devices
 561                         */
 562                        printk(KERN_WARNING
 563                               "%s: p%d size %llu limited to end of disk\n",
 564                               disk->disk_name, p, (unsigned long long) size);
 565                        size = get_capacity(disk) - from;
 566                }
 567                part = add_partition(disk, p, from, size,
 568                                     state->parts[p].flags);
 569                if (IS_ERR(part)) {
 570                        printk(KERN_ERR " %s: p%d could not be added: %ld\n",
 571                               disk->disk_name, p, -PTR_ERR(part));
 572                        continue;
 573                }
 574#ifdef CONFIG_BLK_DEV_MD
 575                if (state->parts[p].flags & ADDPART_FLAG_RAID)
 576                        md_autodetect_dev(part_to_dev(part)->devt);
 577#endif
 578        }
 579        kfree(state);
 580        return 0;
 581}
 582
 583unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
 584{
 585        struct address_space *mapping = bdev->bd_inode->i_mapping;
 586        struct page *page;
 587
 588        page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
 589                                 NULL);
 590        if (!IS_ERR(page)) {
 591                if (PageError(page))
 592                        goto fail;
 593                p->v = page;
 594                return (unsigned char *)page_address(page) +  ((n & ((1 << (PAGE_CACHE_SHIFT - 9)) - 1)) << 9);
 595fail:
 596                page_cache_release(page);
 597        }
 598        p->v = NULL;
 599        return NULL;
 600}
 601
 602EXPORT_SYMBOL(read_dev_sector);
 603
 604void del_gendisk(struct gendisk *disk)
 605{
 606        struct disk_part_iter piter;
 607        struct hd_struct *part;
 608
 609        /* invalidate stuff */
 610        disk_part_iter_init(&piter, disk,
 611                             DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
 612        while ((part = disk_part_iter_next(&piter))) {
 613                invalidate_partition(disk, part->partno);
 614                delete_partition(disk, part->partno);
 615        }
 616        disk_part_iter_exit(&piter);
 617
 618        invalidate_partition(disk, 0);
 619        blk_free_devt(disk_to_dev(disk)->devt);
 620        set_capacity(disk, 0);
 621        disk->flags &= ~GENHD_FL_UP;
 622        unlink_gendisk(disk);
 623        part_stat_set_all(&disk->part0, 0);
 624        disk->part0.stamp = 0;
 625
 626        kobject_put(disk->part0.holder_dir);
 627        kobject_put(disk->slave_dir);
 628        disk->driverfs_dev = NULL;
 629#ifndef CONFIG_SYSFS_DEPRECATED
 630        sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
 631#endif
 632        device_del(disk_to_dev(disk));
 633}
 634
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.