Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dasd_genhd.c
Go to the documentation of this file.
1 /*
2  * Author(s)......: Holger Smolinski <[email protected]>
3  * Horst Hummel <[email protected]>
4  * Carsten Otte <[email protected]>
5  * Martin Schwidefsky <[email protected]>
6  * Bugreports.to..: <[email protected]>
7  * Copyright IBM Corp. 1999, 2001
8  *
9  * gendisk related functions for the dasd driver.
10  *
11  */
12 
13 #define KMSG_COMPONENT "dasd"
14 
15 #include <linux/interrupt.h>
16 #include <linux/fs.h>
17 #include <linux/blkpg.h>
18 
19 #include <asm/uaccess.h>
20 
21 /* This is ugly... */
22 #define PRINTK_HEADER "dasd_gendisk:"
23 
24 #include "dasd_int.h"
25 
26 /*
27  * Allocate and register gendisk structure for device.
28  */
30 {
31  struct gendisk *gdp;
32  struct dasd_device *base;
33  int len;
34 
35  /* Make sure the minor for this device exists. */
36  base = block->base;
37  if (base->devindex >= DASD_PER_MAJOR)
38  return -EBUSY;
39 
40  gdp = alloc_disk(1 << DASD_PARTN_BITS);
41  if (!gdp)
42  return -ENOMEM;
43 
44  /* Initialize gendisk structure. */
45  gdp->major = DASD_MAJOR;
46  gdp->first_minor = base->devindex << DASD_PARTN_BITS;
47  gdp->fops = &dasd_device_operations;
48  gdp->driverfs_dev = &base->cdev->dev;
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 ||
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  add_disk(block->gdp);
80  return 0;
81 }
82 
83 /*
84  * Unregister and free gendisk structure for device.
85  */
87 {
88  if (block->gdp) {
89  del_gendisk(block->gdp);
90  block->gdp->queue = NULL;
91  block->gdp->private_data = NULL;
92  put_disk(block->gdp);
93  block->gdp = NULL;
94  }
95 }
96 
97 /*
98  * Trigger a partition detection.
99  */
101 {
102  struct block_device *bdev;
103 
104  bdev = bdget_disk(block->gdp, 0);
105  if (!bdev || blkdev_get(bdev, FMODE_READ, NULL) < 0)
106  return -ENODEV;
107  /*
108  * See fs/partition/check.c:register_disk,rescan_partitions
109  * Can't call rescan_partitions directly. Use ioctl.
110  */
111  ioctl_by_bdev(bdev, BLKRRPART, 0);
112  /*
113  * Since the matching blkdev_put call to the blkdev_get in
114  * this function is not called before dasd_destroy_partitions
115  * the offline open_count limit needs to be increased from
116  * 0 to 1. This is done by setting device->bdev (see
117  * dasd_generic_set_offline). As long as the partition
118  * detection is running no offline should be allowed. That
119  * is why the assignment to device->bdev is done AFTER
120  * the BLKRRPART ioctl.
121  */
122  block->bdev = bdev;
123  return 0;
124 }
125 
126 /*
127  * Remove all inodes in the system for a device, delete the
128  * partitions and make device unusable by setting its size to zero.
129  */
131 {
132  /* The two structs have 168/176 byte on 31/64 bit. */
133  struct blkpg_partition bpart;
134  struct blkpg_ioctl_arg barg;
135  struct block_device *bdev;
136 
137  /*
138  * Get the bdev pointer from the device structure and clear
139  * device->bdev to lower the offline open_count limit again.
140  */
141  bdev = block->bdev;
142  block->bdev = NULL;
143 
144  /*
145  * See fs/partition/check.c:delete_partition
146  * Can't call delete_partitions directly. Use ioctl.
147  * The ioctl also does locking and invalidation.
148  */
149  memset(&bpart, 0, sizeof(struct blkpg_partition));
150  memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
151  barg.data = (void __force __user *) &bpart;
152  barg.op = BLKPG_DEL_PARTITION;
153  for (bpart.pno = block->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
154  ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
155 
156  invalidate_partition(block->gdp, 0);
157  /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
158  blkdev_put(bdev, FMODE_READ);
159  set_capacity(block->gdp, 0);
160 }
161 
163 {
164  int rc;
165 
166  /* Register to static dasd major 94 */
167  rc = register_blkdev(DASD_MAJOR, "dasd");
168  if (rc != 0) {
169  pr_warning("Registering the device driver with major number "
170  "%d failed\n", DASD_MAJOR);
171  return rc;
172  }
173  return 0;
174 }
175 
177 {
178  unregister_blkdev(DASD_MAJOR, "dasd");
179 }