OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [block/] [ioctl.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <linux/capability.h>
2
#include <linux/blkdev.h>
3
#include <linux/blkpg.h>
4
#include <linux/hdreg.h>
5
#include <linux/backing-dev.h>
6
#include <linux/buffer_head.h>
7
#include <linux/smp_lock.h>
8
#include <linux/blktrace_api.h>
9
#include <asm/uaccess.h>
10
 
11
static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg)
12
{
13
        struct block_device *bdevp;
14
        struct gendisk *disk;
15
        struct blkpg_ioctl_arg a;
16
        struct blkpg_partition p;
17
        long long start, length;
18
        int part;
19
        int i;
20
 
21
        if (!capable(CAP_SYS_ADMIN))
22
                return -EACCES;
23
        if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
24
                return -EFAULT;
25
        if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
26
                return -EFAULT;
27
        disk = bdev->bd_disk;
28
        if (bdev != bdev->bd_contains)
29
                return -EINVAL;
30
        part = p.pno;
31
        if (part <= 0 || part >= disk->minors)
32
                return -EINVAL;
33
        switch (a.op) {
34
                case BLKPG_ADD_PARTITION:
35
                        start = p.start >> 9;
36
                        length = p.length >> 9;
37
                        /* check for fit in a hd_struct */
38
                        if (sizeof(sector_t) == sizeof(long) &&
39
                            sizeof(long long) > sizeof(long)) {
40
                                long pstart = start, plength = length;
41
                                if (pstart != start || plength != length
42
                                    || pstart < 0 || plength < 0)
43
                                        return -EINVAL;
44
                        }
45
                        /* partition number in use? */
46
                        mutex_lock(&bdev->bd_mutex);
47
                        if (disk->part[part - 1]) {
48
                                mutex_unlock(&bdev->bd_mutex);
49
                                return -EBUSY;
50
                        }
51
                        /* overlap? */
52
                        for (i = 0; i < disk->minors - 1; i++) {
53
                                struct hd_struct *s = disk->part[i];
54
 
55
                                if (!s)
56
                                        continue;
57
                                if (!(start+length <= s->start_sect ||
58
                                      start >= s->start_sect + s->nr_sects)) {
59
                                        mutex_unlock(&bdev->bd_mutex);
60
                                        return -EBUSY;
61
                                }
62
                        }
63
                        /* all seems OK */
64
                        add_partition(disk, part, start, length, ADDPART_FLAG_NONE);
65
                        mutex_unlock(&bdev->bd_mutex);
66
                        return 0;
67
                case BLKPG_DEL_PARTITION:
68
                        if (!disk->part[part-1])
69
                                return -ENXIO;
70
                        if (disk->part[part - 1]->nr_sects == 0)
71
                                return -ENXIO;
72
                        bdevp = bdget_disk(disk, part);
73
                        if (!bdevp)
74
                                return -ENOMEM;
75
                        mutex_lock(&bdevp->bd_mutex);
76
                        if (bdevp->bd_openers) {
77
                                mutex_unlock(&bdevp->bd_mutex);
78
                                bdput(bdevp);
79
                                return -EBUSY;
80
                        }
81
                        /* all seems OK */
82
                        fsync_bdev(bdevp);
83
                        invalidate_bdev(bdevp);
84
 
85
                        mutex_lock_nested(&bdev->bd_mutex, 1);
86
                        delete_partition(disk, part);
87
                        mutex_unlock(&bdev->bd_mutex);
88
                        mutex_unlock(&bdevp->bd_mutex);
89
                        bdput(bdevp);
90
 
91
                        return 0;
92
                default:
93
                        return -EINVAL;
94
        }
95
}
96
 
97
static int blkdev_reread_part(struct block_device *bdev)
98
{
99
        struct gendisk *disk = bdev->bd_disk;
100
        int res;
101
 
102
        if (disk->minors == 1 || bdev != bdev->bd_contains)
103
                return -EINVAL;
104
        if (!capable(CAP_SYS_ADMIN))
105
                return -EACCES;
106
        if (!mutex_trylock(&bdev->bd_mutex))
107
                return -EBUSY;
108
        res = rescan_partitions(disk, bdev);
109
        mutex_unlock(&bdev->bd_mutex);
110
        return res;
111
}
112
 
113
static int put_ushort(unsigned long arg, unsigned short val)
114
{
115
        return put_user(val, (unsigned short __user *)arg);
116
}
117
 
118
static int put_int(unsigned long arg, int val)
119
{
120
        return put_user(val, (int __user *)arg);
121
}
122
 
123
static int put_long(unsigned long arg, long val)
124
{
125
        return put_user(val, (long __user *)arg);
126
}
127
 
128
static int put_ulong(unsigned long arg, unsigned long val)
129
{
130
        return put_user(val, (unsigned long __user *)arg);
131
}
132
 
133
static int put_u64(unsigned long arg, u64 val)
134
{
135
        return put_user(val, (u64 __user *)arg);
136
}
137
 
138
static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
139
                                unsigned cmd, unsigned long arg)
140
{
141
        struct backing_dev_info *bdi;
142
        int ret, n;
143
 
144
        switch (cmd) {
145
        case BLKRAGET:
146
        case BLKFRAGET:
147
                if (!arg)
148
                        return -EINVAL;
149
                bdi = blk_get_backing_dev_info(bdev);
150
                if (bdi == NULL)
151
                        return -ENOTTY;
152
                return put_long(arg, (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
153
        case BLKROGET:
154
                return put_int(arg, bdev_read_only(bdev) != 0);
155
        case BLKBSZGET: /* get the logical block size (cf. BLKSSZGET) */
156
                return put_int(arg, block_size(bdev));
157
        case BLKSSZGET: /* get block device hardware sector size */
158
                return put_int(arg, bdev_hardsect_size(bdev));
159
        case BLKSECTGET:
160
                return put_ushort(arg, bdev_get_queue(bdev)->max_sectors);
161
        case BLKRASET:
162
        case BLKFRASET:
163
                if(!capable(CAP_SYS_ADMIN))
164
                        return -EACCES;
165
                bdi = blk_get_backing_dev_info(bdev);
166
                if (bdi == NULL)
167
                        return -ENOTTY;
168
                bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
169
                return 0;
170
        case BLKBSZSET:
171
                /* set the logical block size */
172
                if (!capable(CAP_SYS_ADMIN))
173
                        return -EACCES;
174
                if (!arg)
175
                        return -EINVAL;
176
                if (get_user(n, (int __user *) arg))
177
                        return -EFAULT;
178
                if (bd_claim(bdev, file) < 0)
179
                        return -EBUSY;
180
                ret = set_blocksize(bdev, n);
181
                bd_release(bdev);
182
                return ret;
183
        case BLKPG:
184
                return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg __user *) arg);
185
        case BLKRRPART:
186
                return blkdev_reread_part(bdev);
187
        case BLKGETSIZE:
188
                if ((bdev->bd_inode->i_size >> 9) > ~0UL)
189
                        return -EFBIG;
190
                return put_ulong(arg, bdev->bd_inode->i_size >> 9);
191
        case BLKGETSIZE64:
192
                return put_u64(arg, bdev->bd_inode->i_size);
193
        case BLKTRACESTART:
194
        case BLKTRACESTOP:
195
        case BLKTRACESETUP:
196
        case BLKTRACETEARDOWN:
197
                return blk_trace_ioctl(bdev, cmd, (char __user *) arg);
198
        }
199
        return -ENOIOCTLCMD;
200
}
201
 
202
int blkdev_driver_ioctl(struct inode *inode, struct file *file,
203
                        struct gendisk *disk, unsigned cmd, unsigned long arg)
204
{
205
        int ret;
206
        if (disk->fops->unlocked_ioctl)
207
                return disk->fops->unlocked_ioctl(file, cmd, arg);
208
 
209
        if (disk->fops->ioctl) {
210
                lock_kernel();
211
                ret = disk->fops->ioctl(inode, file, cmd, arg);
212
                unlock_kernel();
213
                return ret;
214
        }
215
 
216
        return -ENOTTY;
217
}
218
EXPORT_SYMBOL_GPL(blkdev_driver_ioctl);
219
 
220
/*
221
 * always keep this in sync with compat_blkdev_ioctl() and
222
 * compat_blkdev_locked_ioctl()
223
 */
224
int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
225
                        unsigned long arg)
226
{
227
        struct block_device *bdev = inode->i_bdev;
228
        struct gendisk *disk = bdev->bd_disk;
229
        int ret, n;
230
 
231
        switch(cmd) {
232
        case BLKFLSBUF:
233
                if (!capable(CAP_SYS_ADMIN))
234
                        return -EACCES;
235
 
236
                ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
237
                /* -EINVAL to handle old uncorrected drivers */
238
                if (ret != -EINVAL && ret != -ENOTTY)
239
                        return ret;
240
 
241
                lock_kernel();
242
                fsync_bdev(bdev);
243
                invalidate_bdev(bdev);
244
                unlock_kernel();
245
                return 0;
246
 
247
        case BLKROSET:
248
                ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
249
                /* -EINVAL to handle old uncorrected drivers */
250
                if (ret != -EINVAL && ret != -ENOTTY)
251
                        return ret;
252
                if (!capable(CAP_SYS_ADMIN))
253
                        return -EACCES;
254
                if (get_user(n, (int __user *)(arg)))
255
                        return -EFAULT;
256
                lock_kernel();
257
                set_device_ro(bdev, n);
258
                unlock_kernel();
259
                return 0;
260
        case HDIO_GETGEO: {
261
                struct hd_geometry geo;
262
 
263
                if (!arg)
264
                        return -EINVAL;
265
                if (!disk->fops->getgeo)
266
                        return -ENOTTY;
267
 
268
                /*
269
                 * We need to set the startsect first, the driver may
270
                 * want to override it.
271
                 */
272
                geo.start = get_start_sect(bdev);
273
                ret = disk->fops->getgeo(bdev, &geo);
274
                if (ret)
275
                        return ret;
276
                if (copy_to_user((struct hd_geometry __user *)arg, &geo,
277
                                        sizeof(geo)))
278
                        return -EFAULT;
279
                return 0;
280
        }
281
        }
282
 
283
        lock_kernel();
284
        ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
285
        unlock_kernel();
286
        if (ret != -ENOIOCTLCMD)
287
                return ret;
288
 
289
        return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
290
}
291
EXPORT_SYMBOL_GPL(blkdev_ioctl);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.