]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.2-blkioctl-sector.patch
- obsolete
[packages/kernel.git] / linux-2.4.2-blkioctl-sector.patch
CommitLineData
95e83f51
JR
1--- linux/include/linux/fs.h.sector Mon Feb 26 23:48:46 2001
2+++ linux/include/linux/fs.h Mon Feb 26 23:53:57 2001
3@@ -187,6 +187,8 @@
4 /* This was here just to show that the number is taken -
5 probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
6 #endif
7+#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
8+#define BLKSETLASTSECT _IO(0x12,109) /* get last sector of block device */
9
10
11 #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */
12--- linux/drivers/block/blkpg.c.sector Fri Oct 27 02:35:47 2000
13+++ linux/drivers/block/blkpg.c Mon Feb 26 23:53:57 2001
14@@ -39,6 +39,9 @@
15
16 #include <asm/uaccess.h>
17
18+static int set_last_sector( kdev_t dev, const void *param );
19+static int get_last_sector( kdev_t dev, const void *param );
20+
21 /*
22 * What is the data describing a partition?
23 *
24@@ -210,6 +213,16 @@
25 int intval;
26
27 switch (cmd) {
28+ case BLKGETLASTSECT:
29+ return get_last_sector(dev, (char *)(arg));
30+
31+ case BLKSETLASTSECT:
32+ if( is_read_only(dev) )
33+ return -EACCES;
34+ if (!capable(CAP_SYS_ADMIN))
35+ return -EACCES;
36+ return set_last_sector(dev, (char *)(arg));
37+
38 case BLKROSET:
39 if (!capable(CAP_SYS_ADMIN))
40 return -EACCES;
41@@ -281,3 +294,209 @@
42 }
43
44 EXPORT_SYMBOL(blk_ioctl);
45+
46+ /*********************
47+ * get_last_sector()
48+ *
49+ * Description: This function will read any inaccessible blocks at the end
50+ * of a device
51+ * Why: Normal read/write calls through the block layer will not read the
52+ * last sector of an odd-size disk.
53+ * parameters:
54+ * dev: kdev_t -- which device to read
55+ * param: a pointer to a userspace struct. The struct has these members:
56+ * block: an int which denotes which block to return:
57+ * 0 == Last block
58+ * 1 == Last block - 1
59+ * n == Last block - n
60+ * This is validated so that only values of
61+ * <= ((total_sects + 1) % logical_block_size) || 0
62+ * are allowed.
63+ * block_contents: a pointer to userspace char*, this is where we write
64+ * returned blocks to.
65+ * content_length: How big the userspace buffer is.
66+ * return:
67+ * 0 on success
68+ * -ERRVAL on error.
69+ *********************/
70+int get_last_sector( kdev_t dev, const void *param )
71+{
72+ struct buffer_head *bh;
73+ struct gendisk *g;
74+ int rc = 0;
75+ unsigned int lastlba, readlba;
76+ int orig_blksize = BLOCK_SIZE;
77+ int hardblocksize;
78+
79+ struct {
80+ unsigned int block;
81+ size_t content_length;
82+ char *block_contents;
83+ } blk_ioctl_parameter;
84+
85+ if( !dev ) return -EINVAL;
86+
87+ if(copy_from_user(&blk_ioctl_parameter, param, sizeof(blk_ioctl_parameter)))
88+ return -EFAULT;
89+
90+ g = get_gendisk( dev );
91+
92+ if( !g ) return -EINVAL;
93+
94+ lastlba = g->part[MINOR(dev)].nr_sects;
95+
96+ if( !lastlba ) return -EINVAL;
97+
c51d8a39 98+ hardblocksize = get_hardsect_size(dev);
95e83f51
JR
99+ if( ! hardblocksize ) hardblocksize = 512;
100+
101+ /* Need to change the block size that the block layer uses */
102+ if (blksize_size[MAJOR(dev)]){
103+ orig_blksize = blksize_size[MAJOR(dev)][MINOR(dev)];
104+ }
105+
106+ /* validate userspace input */
107+ if( blk_ioctl_parameter.block == 0 )
108+ goto good_params;
109+
110+ /* so we don't divide by zero below */
111+ if(orig_blksize == 0)
112+ return -EINVAL;
113+
114+ if( blk_ioctl_parameter.block <= (lastlba % (orig_blksize / hardblocksize)))
115+ goto good_params;
116+
117+ return -EINVAL;
118+
119+good_params:
120+ readlba = lastlba - blk_ioctl_parameter.block - 1;
121+
122+ if (orig_blksize != hardblocksize)
123+ set_blocksize(dev, hardblocksize);
124+
125+ bh = bread(dev, readlba, hardblocksize);
126+ if (!bh) {
127+ /* We hit the end of the disk */
128+ printk(KERN_WARNING
129+ "get_last_sector ioctl: bread returned NULL.\n");
130+ return -1;
131+ }
132+
133+ rc = copy_to_user(blk_ioctl_parameter.block_contents, bh->b_data,
134+ (bh->b_size > blk_ioctl_parameter.content_length) ?
135+ blk_ioctl_parameter.content_length : bh->b_size);
136+
137+ brelse(bh);
138+
139+ /* change block size back */
140+ if (orig_blksize != hardblocksize)
141+ set_blocksize(dev, orig_blksize);
142+
143+ return rc;
144+}
145+
146+ /*********************
147+ * set_last_sector()
148+ *
149+ * Description: This function will write to any inaccessible blocks at the end
150+ * of a device
151+ * Why: Normal read/write calls through the block layer will not read the
152+ * last sector of an odd-size disk.
153+ * parameters:
154+ * dev: kdev_t -- which device to read
155+ * sect: a pointer to a userspace struct. The struct has these members:
156+ * block: an int which denotes which block to return:
157+ * 0 == Last block
158+ * 1 == Last block - 1
159+ * n == Last block - n
160+ * This is validated so that only values of
161+ * <= ((total_sects + 1) % logical_block_size) || 0
162+ * are allowed.
163+ * block_contents: a pointer to userspace char*, this is where we write
164+ * returned blocks to.
165+ * content_length: How big the userspace buffer is.
166+ * return:
167+ * 0 on success
168+ * -ERRVAL on error.
169+ *********************/
170+int set_last_sector( kdev_t dev, const void *param )
171+{
172+ struct buffer_head *bh;
173+ struct gendisk *g;
174+ int rc = 0;
175+ unsigned int lastlba, writelba;
176+ int orig_blksize = BLOCK_SIZE;
177+ int hardblocksize;
178+
179+ struct {
180+ unsigned int block;
181+ size_t content_length;
182+ char *block_contents;
183+ } blk_ioctl_parameter;
184+
185+ if( !dev ) return -EINVAL;
186+
187+ if(copy_from_user(&blk_ioctl_parameter, param, sizeof(blk_ioctl_parameter)))
188+ return -EFAULT;
189+
190+ g = get_gendisk( dev );
191+
192+ if( !g ) return -EINVAL;
193+
194+ lastlba = g->part[MINOR(dev)].nr_sects ;
195+
196+ if( !lastlba ) return -EINVAL;
197+
c51d8a39 198+ hardblocksize = get_hardsect_size(dev);
95e83f51
JR
199+ if( ! hardblocksize ) hardblocksize = 512;
200+
201+ /* Need to change the block size that the block layer uses */
202+ if (blksize_size[MAJOR(dev)]){
203+ orig_blksize = blksize_size[MAJOR(dev)][MINOR(dev)];
204+ }
205+
206+ /* validate userspace input */
207+ if( blk_ioctl_parameter.block == 0 )
208+ goto good_params;
209+
210+ /* so we don't divide by zero below */
211+ if(orig_blksize == 0)
212+ return -EINVAL;
213+
214+ if( blk_ioctl_parameter.block <= (lastlba % (orig_blksize / hardblocksize)))
215+ goto good_params;
216+
217+ return -EINVAL;
218+
219+good_params:
220+ writelba = lastlba - blk_ioctl_parameter.block - 1;
221+
222+ if (orig_blksize != hardblocksize)
223+ set_blocksize(dev, hardblocksize);
224+
225+ bh = bread(dev, writelba, hardblocksize);
226+ if (!bh) {
227+ /* We hit the end of the disk */
228+ printk(KERN_WARNING
229+ "get_last_sector ioctl: getblk returned NULL.\n");
230+ return -1;
231+ }
232+
233+ copy_from_user(bh->b_data, blk_ioctl_parameter.block_contents,
234+ (bh->b_size > blk_ioctl_parameter.content_length) ?
235+ blk_ioctl_parameter.content_length : bh->b_size);
236+
237+ mark_buffer_dirty(bh);
238+ ll_rw_block (WRITE, 1, &bh);
239+ wait_on_buffer (bh);
240+ if (!buffer_uptodate(bh))
241+ rc=-1;
242+
243+ brelse(bh);
244+
245+ /* change block size back */
246+ if (orig_blksize != hardblocksize)
247+ set_blocksize(dev, orig_blksize);
248+
249+ return rc;
250+}
251--- linux/drivers/scsi/sd.c.sector Mon Feb 26 23:48:45 2001
252+++ linux/drivers/scsi/sd.c Mon Feb 26 23:53:57 2001
253@@ -228,6 +228,8 @@
a4d4e290 254 }
255 case BLKGETSIZE:
256 case BLKGETSIZE64:
95e83f51
JR
257+ case BLKGETLASTSECT:
258+ case BLKSETLASTSECT:
259 case BLKROSET:
260 case BLKROGET:
261 case BLKRASET:
262--- linux/drivers/ide/ide.c.sector Mon Feb 26 23:48:49 2001
263+++ linux/drivers/ide/ide.c Mon Feb 26 23:53:57 2001
264@@ -2664,6 +2664,8 @@
265 }
266 return 0;
a4d4e290 267 }
95e83f51
JR
268+ case BLKGETLASTSECT:
269+ case BLKSETLASTSECT:
270 case BLKROSET:
271 case BLKROGET:
272 case BLKFLSBUF:
This page took 0.204667 seconds and 4 git commands to generate.