xd.c patch

Todd T. Fries (friest@acm.org)
Fri, 3 Jan 1997 22:52:05 -0600


--uLvjFFCVXOIeQyS3

I have found that the 'cylinders' was not prototyped at all in drivers/block/xd.c leading
to bogus values of, say, 16xxx when the true value was 615. This patch fixes
that, and cleans up the xd_ioctl() function.

I noticed, in the process of finding out why this bogus geometry was returned
that most 'hard disk' like devices have a common subset of ioctls. Perhaps
something could be done rather than maintaining about three to four <hard drive>_ioctl
functions that have exactly duplicated code (e.g. HDIO_GETGEO?) Perhaps something along
the lines of the cdrom.c implementation?

I started trying to implement hd_ioctl.c, but there is a usage count incremented
for every ioctl command issued, specific to each device. Should this behave like
cdrom.c suggests, and only block open requests if it is something other than O_NONBLK,
so that ioctl commands can be given independent of reading and writing?

Anyway, here is the patch..
-- Todd T. Fries .. friest@acm.org


--- xd.c.old Tue Nov 26 22:57:20 1996
+++ xd.c Fri Jan 3 21:16:58 1997
@@ -29,6 +29,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
+#include <linux/hdreg.h>

#include <asm/system.h>
#include <asm/io.h>
@@ -250,77 +251,75 @@
/* xd_ioctl: handle device ioctl's */
static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{
- XD_GEOMETRY *geometry = (XD_GEOMETRY *) arg;
- int dev = DEVICE_NR(inode->i_rdev),err;
+ int dev;

- if (inode && (dev < xd_drives))
- switch (cmd) {
- case HDIO_GETGEO:
- if (arg) {
- if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
- return (err);
- put_user(xd_info[dev].heads, &geometry->heads);
- put_user(xd_info[dev].sectors, &geometry->sectors);
- put_user(xd_info[dev].cylinders, &geometry->cylinders);
- put_user(xd[MINOR(inode->i_rdev)].start_sect,&geometry->start);
-
- return (0);
- }
- break;
- case BLKRASET:
- if(!suser())
- return -EACCES;
- if(!(inode->i_rdev))
- return -EINVAL;
- if(arg > 0xff)
- return -EINVAL;
- read_ahead[MAJOR(inode->i_rdev)] = arg;
- return 0;
- case BLKGETSIZE:
- if (arg) {
- if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
- return (err);
- put_user(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
-
- return (0);
- }
- break;
- case BLKFLSBUF:
- if(!suser()) return -EACCES;
- if(!(inode->i_rdev))
- return -EINVAL;
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- return 0;
-
- case BLKRRPART:
- return (xd_reread_partitions(inode->i_rdev));
- RO_IOCTLS(inode->i_rdev,arg);
+ if ((!inode) || !(inode->i_rdev))
+ return -EINVAL;
+ dev = DEVICE_NR(inode->i_rdev);
+
+ if (dev >= xd_drives) return -EINVAL;
+ switch (cmd) {
+ case HDIO_GETGEO:
+ {
+ struct hd_geometry *geometry = (struct hd_geometry *) arg;
+ if (!geometry) return -EINVAL;
+ if(put_user(xd_info[dev].heads, (char *) &geometry->heads)
+ || put_user(xd_info[dev].sectors, (char *) &geometry->sectors)
+ || put_user(xd_info[dev].cylinders, (short *) &geometry->cylinders)
+ || put_user(xd[MINOR(inode->i_rdev)].start_sect,
+ (unsigned long *) &geometry->start))
+ return -EFAULT;
+ return 0;
}
- return (-EINVAL);
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(arg > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = arg;
+ return 0;
+ case BLKGETSIZE:
+ if (!arg) return -EINVAL;
+ put_user(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
+ return 0;
+ case BLKFLSBUF: /* Return devices size */
+ if(!suser()) return -EACCES;
+ fsync_dev(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
+ return 0;
+ case BLKRRPART:
+ return xd_reread_partitions(inode->i_rdev);
+ RO_IOCTLS(inode->i_rdev,arg);
+ default:
+ return -EINVAL;
+ }
}

/* xd_release: release the device */
static void xd_release (struct inode *inode, struct file *file)
{
- int dev = DEVICE_NR(inode->i_rdev);
+ int target;

- if (dev < xd_drives) {
+ target= DEVICE_NR(inode->i_rdev);
+ if (target < xd_drives) {
sync_dev(inode->i_rdev);
- xd_access[dev]--;
+ xd_access[target]--;
}
}

/* xd_reread_partitions: rereads the partition table from a drive */
static int xd_reread_partitions(kdev_t dev)
{
- int target = DEVICE_NR(dev);
- int start = target << xd_gendisk.minor_shift;
+ int target;
+ int start;
int partition;
-
- cli(); xd_valid[target] = (xd_access[target] != 1); sti();
+
+ target = DEVICE_NR(dev);
+ start = target << xd_gendisk.minor_shift;
+
+ cli();
+ xd_valid[target] = (xd_access[target] != 1);
+ sti();
if (xd_valid[target])
- return (-EBUSY);
+ return -EBUSY;

for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
int minor = (start | partition);
@@ -338,7 +337,7 @@
xd_valid[target] = 1;
wake_up(&xd_wait_open);

- return (0);
+ return 0;
}

/* xd_readwrite: handle a read/write request */

--uLvjFFCVXOIeQyS3
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3

iQCVAwUBMs3h8f7ywgyYzp5ZAQFmAAQAoyZ41P0iy19UPRpPpGh/JiHXotNDKLIp
xWxUL1vfM5mQ94MRz/gHQOIB4r4bSetuQqYq5aBBWbO3xyZGxYrhzuts0lKogAix
F/BP+dLb+T68Kj9XLCACLQ+nESna9D4gWyt3RyK8Rgmzr/UJ8WnbuLUcGBtYxIK1
vA9FN1kgJfA=
=FHVJ
-----END PGP SIGNATURE-----

--uLvjFFCVXOIeQyS3--