root/drivers/s390/block/dasd_genhd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dasd_gendisk_alloc
  2. dasd_gendisk_free
  3. dasd_scan_partitions
  4. dasd_destroy_partitions
  5. dasd_gendisk_init
  6. dasd_gendisk_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
   4  *                  Horst Hummel <Horst.Hummel@de.ibm.com>
   5  *                  Carsten Otte <Cotte@de.ibm.com>
   6  *                  Martin Schwidefsky <schwidefsky@de.ibm.com>
   7  * Bugreports.to..: <Linux390@de.ibm.com>
   8  * Copyright IBM Corp. 1999, 2001
   9  *
  10  * gendisk related functions for the dasd driver.
  11  *
  12  */
  13 
  14 #define KMSG_COMPONENT "dasd"
  15 
  16 #include <linux/interrupt.h>
  17 #include <linux/fs.h>
  18 #include <linux/blkpg.h>
  19 
  20 #include <linux/uaccess.h>
  21 
  22 /* This is ugly... */
  23 #define PRINTK_HEADER "dasd_gendisk:"
  24 
  25 #include "dasd_int.h"
  26 
  27 /*
  28  * Allocate and register gendisk structure for device.
  29  */
  30 int dasd_gendisk_alloc(struct dasd_block *block)
  31 {
  32         struct gendisk *gdp;
  33         struct dasd_device *base;
  34         int len;
  35 
  36         /* Make sure the minor for this device exists. */
  37         base = block->base;
  38         if (base->devindex >= DASD_PER_MAJOR)
  39                 return -EBUSY;
  40 
  41         gdp = alloc_disk(1 << DASD_PARTN_BITS);
  42         if (!gdp)
  43                 return -ENOMEM;
  44 
  45         /* Initialize gendisk structure. */
  46         gdp->major = DASD_MAJOR;
  47         gdp->first_minor = base->devindex << DASD_PARTN_BITS;
  48         gdp->fops = &dasd_device_operations;
  49 
  50         /*
  51          * Set device name.
  52          *   dasda - dasdz : 26 devices
  53          *   dasdaa - dasdzz : 676 devices, added up = 702
  54          *   dasdaaa - dasdzzz : 17576 devices, added up = 18278
  55          *   dasdaaaa - dasdzzzz : 456976 devices, added up = 475252
  56          */
  57         len = sprintf(gdp->disk_name, "dasd");
  58         if (base->devindex > 25) {
  59                 if (base->devindex > 701) {
  60                         if (base->devindex > 18277)
  61                                 len += sprintf(gdp->disk_name + len, "%c",
  62                                                'a'+(((base->devindex-18278)
  63                                                      /17576)%26));
  64                         len += sprintf(gdp->disk_name + len, "%c",
  65                                        'a'+(((base->devindex-702)/676)%26));
  66                 }
  67                 len += sprintf(gdp->disk_name + len, "%c",
  68                                'a'+(((base->devindex-26)/26)%26));
  69         }
  70         len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
  71 
  72         if (base->features & DASD_FEATURE_READONLY ||
  73             test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
  74                 set_disk_ro(gdp, 1);
  75         dasd_add_link_to_gendisk(gdp, base);
  76         gdp->queue = block->request_queue;
  77         block->gdp = gdp;
  78         set_capacity(block->gdp, 0);
  79         device_add_disk(&base->cdev->dev, block->gdp, NULL);
  80         return 0;
  81 }
  82 
  83 /*
  84  * Unregister and free gendisk structure for device.
  85  */
  86 void dasd_gendisk_free(struct dasd_block *block)
  87 {
  88         if (block->gdp) {
  89                 del_gendisk(block->gdp);
  90                 block->gdp->private_data = NULL;
  91                 put_disk(block->gdp);
  92                 block->gdp = NULL;
  93         }
  94 }
  95 
  96 /*
  97  * Trigger a partition detection.
  98  */
  99 int dasd_scan_partitions(struct dasd_block *block)
 100 {
 101         struct block_device *bdev;
 102         int rc;
 103 
 104         bdev = bdget_disk(block->gdp, 0);
 105         if (!bdev) {
 106                 DBF_DEV_EVENT(DBF_ERR, block->base, "%s",
 107                               "scan partitions error, bdget returned NULL");
 108                 return -ENODEV;
 109         }
 110 
 111         rc = blkdev_get(bdev, FMODE_READ, NULL);
 112         if (rc < 0) {
 113                 DBF_DEV_EVENT(DBF_ERR, block->base,
 114                               "scan partitions error, blkdev_get returned %d",
 115                               rc);
 116                 return -ENODEV;
 117         }
 118 
 119         rc = blkdev_reread_part(bdev);
 120         if (rc)
 121                 DBF_DEV_EVENT(DBF_ERR, block->base,
 122                                 "scan partitions error, rc %d", rc);
 123 
 124         /*
 125          * Since the matching blkdev_put call to the blkdev_get in
 126          * this function is not called before dasd_destroy_partitions
 127          * the offline open_count limit needs to be increased from
 128          * 0 to 1. This is done by setting device->bdev (see
 129          * dasd_generic_set_offline). As long as the partition
 130          * detection is running no offline should be allowed. That
 131          * is why the assignment to device->bdev is done AFTER
 132          * the BLKRRPART ioctl.
 133          */
 134         block->bdev = bdev;
 135         return 0;
 136 }
 137 
 138 /*
 139  * Remove all inodes in the system for a device, delete the
 140  * partitions and make device unusable by setting its size to zero.
 141  */
 142 void dasd_destroy_partitions(struct dasd_block *block)
 143 {
 144         /* The two structs have 168/176 byte on 31/64 bit. */
 145         struct blkpg_partition bpart;
 146         struct blkpg_ioctl_arg barg;
 147         struct block_device *bdev;
 148 
 149         /*
 150          * Get the bdev pointer from the device structure and clear
 151          * device->bdev to lower the offline open_count limit again.
 152          */
 153         bdev = block->bdev;
 154         block->bdev = NULL;
 155 
 156         /*
 157          * See fs/partition/check.c:delete_partition
 158          * Can't call delete_partitions directly. Use ioctl.
 159          * The ioctl also does locking and invalidation.
 160          */
 161         memset(&bpart, 0, sizeof(struct blkpg_partition));
 162         memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
 163         barg.data = (void __force __user *) &bpart;
 164         barg.op = BLKPG_DEL_PARTITION;
 165         for (bpart.pno = block->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
 166                 ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
 167 
 168         invalidate_partition(block->gdp, 0);
 169         /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
 170         blkdev_put(bdev, FMODE_READ);
 171         set_capacity(block->gdp, 0);
 172 }
 173 
 174 int dasd_gendisk_init(void)
 175 {
 176         int rc;
 177 
 178         /* Register to static dasd major 94 */
 179         rc = register_blkdev(DASD_MAJOR, "dasd");
 180         if (rc != 0) {
 181                 pr_warn("Registering the device driver with major number %d failed\n",
 182                         DASD_MAJOR);
 183                 return rc;
 184         }
 185         return 0;
 186 }
 187 
 188 void dasd_gendisk_exit(void)
 189 {
 190         unregister_blkdev(DASD_MAJOR, "dasd");
 191 }

/* [<][>][^][v][top][bottom][index][help] */