~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/drivers/block/genhd.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Code extracted from
3
 
 *  linux/kernel/hd.c
4
 
 *
5
 
 *  Copyright (C) 1991-1998  Linus Torvalds
6
 
 *
7
 
 *  devfs support - jj, rgooch, 980122
8
 
 *
9
 
 *  Moved partition checking code to fs/partitions* - Russell King
10
 
 *  (linux@arm.uk.linux.org)
11
 
 */
12
 
 
13
 
/*
14
 
 * TODO:  rip out the remaining init crap from this file  --hch
15
 
 */
16
 
 
17
 
#include <xeno/config.h>
18
 
#include <xeno/module.h>
19
 
/*#include <xeno/fs.h>*/
20
 
#include <xeno/genhd.h>
21
 
#include <xeno/lib.h>
22
 
#include <xeno/blk.h>
23
 
#include <xeno/init.h>
24
 
#include <xeno/spinlock.h>
25
 
 
26
 
 
27
 
static rwlock_t gendisk_lock;
28
 
 
29
 
/*
30
 
 * Global kernel list of partitioning information.
31
 
 *
32
 
 * XXX: you should _never_ access this directly.
33
 
 *      the only reason this is exported is source compatiblity.
34
 
 */
35
 
/*static*/ struct gendisk *gendisk_head;
36
 
static struct gendisk *gendisk_array[MAX_BLKDEV];
37
 
 
38
 
EXPORT_SYMBOL(gendisk_head);
39
 
 
40
 
 
41
 
/**
42
 
 * add_gendisk - add partitioning information to kernel list
43
 
 * @gp: per-device partitioning information
44
 
 *
45
 
 * This function registers the partitioning information in @gp
46
 
 * with the kernel.
47
 
 */
48
 
void
49
 
add_gendisk(struct gendisk *gp)
50
 
{
51
 
        struct gendisk *sgp;
52
 
 
53
 
        write_lock(&gendisk_lock);
54
 
 
55
 
        /*
56
 
         *      In 2.5 this will go away. Fix the drivers who rely on
57
 
         *      old behaviour.
58
 
         */
59
 
 
60
 
        for (sgp = gendisk_head; sgp; sgp = sgp->next)
61
 
        {
62
 
                if (sgp == gp)
63
 
                {
64
 
//                      printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
65
 
//                              sgp->major)
66
 
                        goto out;
67
 
                }
68
 
        }
69
 
        gendisk_array[gp->major] = gp;
70
 
        gp->next = gendisk_head;
71
 
        gendisk_head = gp;
72
 
out:
73
 
        write_unlock(&gendisk_lock);
74
 
}
75
 
 
76
 
EXPORT_SYMBOL(add_gendisk);
77
 
 
78
 
 
79
 
/**
80
 
 * del_gendisk - remove partitioning information from kernel list
81
 
 * @gp: per-device partitioning information
82
 
 *
83
 
 * This function unregisters the partitioning information in @gp
84
 
 * with the kernel.
85
 
 */
86
 
void
87
 
del_gendisk(struct gendisk *gp)
88
 
{
89
 
        struct gendisk **gpp;
90
 
 
91
 
        write_lock(&gendisk_lock);
92
 
        gendisk_array[gp->major] = NULL;
93
 
        for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
94
 
                if (*gpp == gp)
95
 
                        break;
96
 
        if (*gpp)
97
 
                *gpp = (*gpp)->next;
98
 
        write_unlock(&gendisk_lock);
99
 
}
100
 
 
101
 
EXPORT_SYMBOL(del_gendisk);
102
 
 
103
 
 
104
 
/**
105
 
 * get_gendisk - get partitioning information for a given device
106
 
 * @dev: device to get partitioning information for
107
 
 *
108
 
 * This function gets the structure containing partitioning
109
 
 * information for the given device @dev.
110
 
 */
111
 
struct gendisk *
112
 
get_gendisk(kdev_t dev)
113
 
{
114
 
        struct gendisk *gp = NULL;
115
 
        int maj = MAJOR(dev);
116
 
 
117
 
        read_lock(&gendisk_lock);
118
 
        if ((gp = gendisk_array[maj]))
119
 
                goto out;
120
 
 
121
 
        /* This is needed for early 2.4 source compatiblity.  --hch */
122
 
        for (gp = gendisk_head; gp; gp = gp->next)
123
 
                if (gp->major == maj)
124
 
                        break;
125
 
out:
126
 
        read_unlock(&gendisk_lock);
127
 
        return gp;
128
 
}
129
 
 
130
 
EXPORT_SYMBOL(get_gendisk);
131
 
 
132
 
 
133
 
/**
134
 
 * walk_gendisk - issue a command for every registered gendisk
135
 
 * @walk: user-specified callback
136
 
 * @data: opaque data for the callback
137
 
 *
138
 
 * This function walks through the gendisk chain and calls back
139
 
 * into @walk for every element.
140
 
 */
141
 
int
142
 
walk_gendisk(int (*walk)(struct gendisk *, void *), void *data)
143
 
{
144
 
        struct gendisk *gp;
145
 
        int error = 0;
146
 
 
147
 
        read_lock(&gendisk_lock);
148
 
        for (gp = gendisk_head; gp; gp = gp->next)
149
 
                if ((error = walk(gp, data)))
150
 
                        break;
151
 
        read_unlock(&gendisk_lock);
152
 
 
153
 
        return error;
154
 
}
155
 
 
156
 
 
157
 
#ifdef CONFIG_PROC_FS
158
 
int
159
 
get_partition_list(char *page, char **start, off_t offset, int count)
160
 
{
161
 
        struct gendisk *gp;
162
 
        struct hd_struct *hd;
163
 
        char buf[64];
164
 
        int len, n;
165
 
 
166
 
        len = sprintf(page, "major minor  #blocks  name\n\n");
167
 
                
168
 
        read_lock(&gendisk_lock);
169
 
        for (gp = gendisk_head; gp; gp = gp->next) {
170
 
                for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
171
 
                        if (gp->part[n].nr_sects == 0)
172
 
                                continue;
173
 
 
174
 
                        hd = &gp->part[n]; disk_round_stats(hd);
175
 
                        len += sprintf(page + len,
176
 
                                "%4d  %4d %10d %s\n", gp->major,
177
 
                                n, gp->sizes[n], disk_name(gp, n, buf));
178
 
 
179
 
                        if (len < offset)
180
 
                                offset -= len, len = 0;
181
 
                        else if (len >= offset + count)
182
 
                                goto out;
183
 
                }
184
 
        }
185
 
 
186
 
out:
187
 
        read_unlock(&gendisk_lock);
188
 
        *start = page + offset;
189
 
        len -= offset;
190
 
        if (len < 0)
191
 
                len = 0;
192
 
        return len > count ? count : len;
193
 
}
194
 
#endif
195
 
 
196
 
/* XXX SMH: stuff from fs/partitions dumped here temporarily */
197
 
 
198
 
 
199
 
/*
200
 
 * This function will re-read the partition tables for a given device,
201
 
 * and set things back up again.  There are some important caveats,
202
 
 * however.  You must ensure that no one is using the device, and no one
203
 
 * can start using the device while this function is being executed.
204
 
 *
205
 
 * Much of the cleanup from the old partition tables should have already been
206
 
 * done
207
 
 */
208
 
void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
209
 
    struct block_device_operations *ops, long size)
210
 
{
211
 
    if (!gdev)
212
 
        return;
213
 
    grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
214
 
}
215
 
 
216
 
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
217
 
{
218
 
        int i;
219
 
        int first_minor = drive << dev->minor_shift;
220
 
        int end_minor   = first_minor + dev->max_p;
221
 
 
222
 
        if(!dev->sizes)
223
 
                blk_size[dev->major] = NULL;
224
 
 
225
 
        dev->part[first_minor].nr_sects = size;
226
 
#ifdef DEVFS_MUST_DIE
227
 
        /* No such device or no minors to use for partitions */
228
 
        if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
229
 
                devfs_register_partitions (dev, first_minor, 0);
230
 
#endif
231
 
 
232
 
        if (!size || minors == 1)
233
 
                return;
234
 
 
235
 
        if (dev->sizes) {
236
 
                dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
237
 
                for (i = first_minor + 1; i < end_minor; i++)
238
 
                        dev->sizes[i] = 0;
239
 
        }
240
 
        blk_size[dev->major] = dev->sizes;
241
 
#if 0
242
 
        /* XXX SMH: don't actually check partition details yet */
243
 
        check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
244
 
#endif
245
 
 
246
 
        /*
247
 
         * We need to set the sizes array before we will be able to access
248
 
         * any of the partitions on this device.
249
 
         */
250
 
        if (dev->sizes != NULL) {       /* optional safeguard in ll_rw_blk.c */
251
 
                for (i = first_minor; i < end_minor; i++)
252
 
                        dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
253
 
        }
254
 
}
255
 
 
256
 
 
257
 
 
258
 
extern int blk_dev_init(void);
259
 
extern int net_dev_init(void);
260
 
extern void console_map_init(void);
261
 
extern int atmdev_init(void);
262
 
 
263
 
int __init device_init(void)
264
 
{
265
 
        rwlock_init(&gendisk_lock);
266
 
        blk_dev_init();
267
 
        sti();
268
 
#ifdef CONFIG_NET
269
 
        net_dev_init();
270
 
#endif
271
 
#ifdef CONFIG_ATM
272
 
        (void) atmdev_init();
273
 
#endif
274
 
#ifdef CONFIG_VT
275
 
        console_map_init();
276
 
#endif
277
 
        return 0;
278
 
}
279
 
 
280
 
__initcall(device_init);