~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/raw.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/drivers/char/raw.c
  3  *
  4  * Front-end raw character devices.  These can be bound to any block
  5  * devices to provide genuine Unix raw character device semantics.
  6  *
  7  * We reserve minor number 0 for a control interface.  ioctl()s on this
  8  * device are used to bind the other minor numbers to block devices.
  9  */
 10 
 11 #include <linux/fs.h>
 12 #include <linux/iobuf.h>
 13 #include <linux/major.h>
 14 #include <linux/blkdev.h>
 15 #include <linux/raw.h>
 16 #include <linux/capability.h>
 17 #include <linux/smp_lock.h>
 18 #include <asm/uaccess.h>
 19 
 20 #define dprintk(x...) 
 21 
 22 static struct block_device *raw_device_bindings[256];
 23 static int raw_device_inuse[256];
 24 static int raw_device_sector_size[256];
 25 static int raw_device_sector_bits[256];
 26 
 27 static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
 28 
 29 ssize_t raw_read(struct file *, char *, size_t, loff_t *);
 30 ssize_t raw_write(struct file *, const char *, size_t, loff_t *);
 31 int     raw_open(struct inode *, struct file *);
 32 int     raw_release(struct inode *, struct file *);
 33 int     raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 34 
 35 
 36 static struct file_operations raw_fops = {
 37         read:           raw_read,
 38         write:          raw_write,
 39         open:           raw_open,
 40         release:        raw_release,
 41 };
 42 
 43 static struct file_operations raw_ctl_fops = {
 44         ioctl:          raw_ctl_ioctl,
 45         open:           raw_open,
 46 };
 47 
 48 void __init raw_init(void)
 49 {
 50         register_chrdev(RAW_MAJOR, "raw", &raw_fops);
 51 }
 52 
 53 /* 
 54  * Open/close code for raw IO.
 55  */
 56 
 57 int raw_open(struct inode *inode, struct file *filp)
 58 {
 59         int minor;
 60         struct block_device * bdev;
 61         kdev_t rdev;    /* it should eventually go away */
 62         int err;
 63         int sector_size;
 64         int sector_bits;
 65 
 66         minor = MINOR(inode->i_rdev);
 67         
 68         /* 
 69          * Is it the control device? 
 70          */
 71         
 72         if (minor == 0) {
 73                 filp->f_op = &raw_ctl_fops;
 74                 return 0;
 75         }
 76         
 77         /*
 78          * No, it is a normal raw device.  All we need to do on open is
 79          * to check that the device is bound, and force the underlying
 80          * block device to a sector-size blocksize. 
 81          */
 82 
 83         bdev = raw_device_bindings[minor];
 84         if (!bdev)
 85                 return -ENODEV;
 86 
 87         rdev = to_kdev_t(bdev->bd_dev);
 88         err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
 89         if (err)
 90                 return err;
 91         
 92         /*
 93          * Don't change the blocksize if we already have users using
 94          * this device 
 95          */
 96 
 97         if (raw_device_inuse[minor]++)
 98                 return 0;
 99         
100         /* 
101          * Don't interfere with mounted devices: we cannot safely set
102          * the blocksize on a device which is already mounted.  
103          */
104         
105         sector_size = 512;
106         if (get_super(rdev) != NULL) {
107                 if (blksize_size[MAJOR(rdev)])
108                         sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
109         } else {
110                 if (hardsect_size[MAJOR(rdev)])
111                         sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];
112         }
113 
114         set_blocksize(rdev, sector_size);
115         raw_device_sector_size[minor] = sector_size;
116 
117         for (sector_bits = 0; !(sector_size & 1); )
118                 sector_size>>=1, sector_bits++;
119         raw_device_sector_bits[minor] = sector_bits;
120         
121         return 0;
122 }
123 
124 int raw_release(struct inode *inode, struct file *filp)
125 {
126         int minor;
127         struct block_device *bdev;
128         
129         minor = MINOR(inode->i_rdev);
130         lock_kernel();
131         bdev = raw_device_bindings[minor];
132         blkdev_put(bdev, BDEV_RAW);
133         raw_device_inuse[minor]--;
134         unlock_kernel();
135         return 0;
136 }
137 
138 
139 
140 /*
141  * Deal with ioctls against the raw-device control interface, to bind
142  * and unbind other raw devices.  
143  */
144 
145 int raw_ctl_ioctl(struct inode *inode, 
146                   struct file *flip,
147                   unsigned int command, 
148                   unsigned long arg)
149 {
150         struct raw_config_request rq;
151         int err = 0;
152         int minor;
153         
154         switch (command) {
155         case RAW_SETBIND:
156         case RAW_GETBIND:
157 
158                 /* First, find out which raw minor we want */
159 
160                 err = copy_from_user(&rq, (void *) arg, sizeof(rq));
161                 if (err)
162                         break;
163                 
164                 minor = rq.raw_minor;
165                 if (minor == 0 || minor > MINORMASK) {
166                         err = -EINVAL;
167                         break;
168                 }
169 
170                 if (command == RAW_SETBIND) {
171                         /*
172                          * This is like making block devices, so demand the
173                          * same capability
174                          */
175                         if (!capable(CAP_SYS_ADMIN)) {
176                                 err = -EPERM;
177                                 break;
178                         }
179 
180                         /* 
181                          * For now, we don't need to check that the underlying
182                          * block device is present or not: we can do that when
183                          * the raw device is opened.  Just check that the
184                          * major/minor numbers make sense. 
185                          */
186 
187                         if (rq.block_major == NODEV || 
188                             rq.block_major > MAX_BLKDEV ||
189                             rq.block_minor > MINORMASK) {
190                                 err = -EINVAL;
191                                 break;
192                         }
193                         
194                         if (raw_device_inuse[minor]) {
195                                 err = -EBUSY;
196                                 break;
197                         }
198                         if (raw_device_bindings[minor])
199                                 bdput(raw_device_bindings[minor]);
200                         raw_device_bindings[minor] = 
201                                 bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
202                 } else {
203                         struct block_device *bdev;
204                         kdev_t dev;
205 
206                         bdev = raw_device_bindings[minor];
207                         if (bdev) {
208                                 dev = to_kdev_t(bdev->bd_dev);
209                                 rq.block_major = MAJOR(dev);
210                                 rq.block_minor = MINOR(dev);
211                         } else {
212                                 rq.block_major = rq.block_minor = 0;
213                         }
214                         err = copy_to_user((void *) arg, &rq, sizeof(rq));
215                 }
216                 break;
217                 
218         default:
219                 err = -EINVAL;
220         }
221         
222         return err;
223 }
224 
225 
226 
227 ssize_t raw_read(struct file *filp, char * buf, 
228                  size_t size, loff_t *offp)
229 {
230         return rw_raw_dev(READ, filp, buf, size, offp);
231 }
232 
233 ssize_t raw_write(struct file *filp, const char *buf, 
234                   size_t size, loff_t *offp)
235 {
236         return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);
237 }
238 
239 #define SECTOR_BITS 9
240 #define SECTOR_SIZE (1U << SECTOR_BITS)
241 #define SECTOR_MASK (SECTOR_SIZE - 1)
242 
243 ssize_t rw_raw_dev(int rw, struct file *filp, char *buf, 
244                    size_t size, loff_t *offp)
245 {
246         struct kiobuf * iobuf;
247         int             err;
248         unsigned long   blocknr, blocks;
249         unsigned long   b[KIO_MAX_SECTORS];
250         size_t          transferred;
251         int             iosize;
252         int             i;
253         int             minor;
254         kdev_t          dev;
255         unsigned long   limit;
256 
257         int             sector_size, sector_bits, sector_mask;
258         int             max_sectors;
259         
260         /*
261          * First, a few checks on device size limits 
262          */
263 
264         minor = MINOR(filp->f_dentry->d_inode->i_rdev);
265         dev = to_kdev_t(raw_device_bindings[minor]->bd_dev);
266         sector_size = raw_device_sector_size[minor];
267         sector_bits = raw_device_sector_bits[minor];
268         sector_mask = sector_size- 1;
269         max_sectors = KIO_MAX_SECTORS >> (sector_bits - 9);
270         
271         if (blk_size[MAJOR(dev)])
272                 limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
273         else
274                 limit = INT_MAX;
275         dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",
276                  MAJOR(dev), MINOR(dev), limit);
277         
278         if ((*offp & sector_mask) || (size & sector_mask))
279                 return -EINVAL;
280         if ((*offp >> sector_bits) > limit)
281                 return 0;
282 
283         /* 
284          * We'll just use one kiobuf
285          */
286 
287         err = alloc_kiovec(1, &iobuf);
288         if (err)
289                 return err;
290 
291         /*
292          * Split the IO into KIO_MAX_SECTORS chunks, mapping and
293          * unmapping the single kiobuf as we go to perform each chunk of
294          * IO.  
295          */
296 
297         transferred = 0;
298         blocknr = *offp >> sector_bits;
299         while (size > 0) {
300                 blocks = size >> sector_bits;
301                 if (blocks > max_sectors)
302                         blocks = max_sectors;
303                 if (blocks > limit - blocknr)
304                         blocks = limit - blocknr;
305                 if (!blocks)
306                         break;
307 
308                 iosize = blocks << sector_bits;
309 
310                 err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
311                 if (err)
312                         break;
313 #if 0
314                 err = lock_kiovec(1, &iobuf, 1);
315                 if (err) 
316                         break;
317 #endif
318         
319                 for (i=0; i < blocks; i++) 
320                         b[i] = blocknr++;
321                 
322                 err = brw_kiovec(rw, 1, &iobuf, dev, b, sector_size);
323 
324                 if (err >= 0) {
325                         transferred += err;
326                         size -= err;
327                         buf += err;
328                 }
329 
330                 unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
331 
332                 if (err != iosize)
333                         break;
334         }
335         
336         free_kiovec(1, &iobuf);
337 
338         if (transferred) {
339                 *offp += transferred;
340                 return transferred;
341         }
342         
343         return err;
344 }
345 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.