History

Merge branch 'block-dev'

Merge 'block-dev' branch. I was going to just mark everything here for stable and leave it to the 3.8 merge window, but having decided on doing another -rc, I migth as well merge it now. This removes the bd_block_size_semaphore semaphore that was added in this release to fix a race condition between block size changes and block IO, and replaces it with atomicity guaratees in fs/buffer.c instead, along with simplifying fs/block-dev.c. This removes more lines than it adds, makes the code generally simpler, and avoids the latency/rt issues that the block size semaphore introduced for mount. I'm not happy with the timing, but it wouldn't be much better doing this during the merge window and then having some delayed back-port of it into stable. * block-dev: blkdev_max_block: make private to fs/buffer.c direct-io: don't read inode->i_blkbits multiple times blockdev: remove bd_block_size_semaphore again fs/buffer.c: make block-size be per-page and protected by the page lock

Linus Torvalds committed 13 years ago

Commit d3594ea2 parents 7e5530a bbec0275 files · +72 −196Browse files

Unified · Split

5 files
  1. drivers/char/raw.c +1 −1
  2. fs/block_dev.c +5 −155
  3. fs/buffer.c +61 −32
  4. fs/direct-io.c +5 −3
  5. include/linux/fs.h +0 −5
drivers/char/raw.c+1−1
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd, · 284 unmodified lines
285285
286286 static const struct file_operations raw_fops = {
287287 .read = do_sync_read,
288− .aio_read = blkdev_aio_read,
288+ .aio_read = generic_file_aio_read,
289289 .write = do_sync_write,
290290 .aio_write = blkdev_aio_write,
291291 .fsync = blkdev_fsync,
fs/block_dev.c+5−155
@@ -70,19 +70,6 @@ static void bdev_inode_switch_bdi(struct inode *inode, · 69 unmodified lines
7070 spin_unlock(&dst->wb.list_lock);
7171 }
7272
73−sector_t blkdev_max_block(struct block_device *bdev)
74−{
75− sector_t retval = ~((sector_t)0);
76− loff_t sz = i_size_read(bdev->bd_inode);
77−
78− if (sz) {
79− unsigned int size = block_size(bdev);
80− unsigned int sizebits = blksize_bits(size);
81− retval = (sz >> sizebits);
82− }
83− return retval;
84−}
85−
8673 /* Kill _all_ buffers and pagecache , dirty or not.. */
8774 void kill_bdev(struct block_device *bdev)
8875 {
@@ -116,8 +103,6 @@ EXPORT_SYMBOL(invalidate_bdev); · 27 unmodified lines
116103
117104 int set_blocksize(struct block_device *bdev, int size)
118105 {
119− struct address_space *mapping;
120−
121106 /* Size must be a power of two, and between 512 and PAGE_SIZE */
122107 if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
123108 return -EINVAL;
@@ -126,19 +111,6 @@ int set_blocksize(struct block_device *bdev, int size) · 2 unmodified lines
126111 if (size < bdev_logical_block_size(bdev))
127112 return -EINVAL;
128113
129− /* Prevent starting I/O or mapping the device */
130− percpu_down_write(&bdev->bd_block_size_semaphore);
131−
132− /* Check that the block device is not memory mapped */
133− mapping = bdev->bd_inode->i_mapping;
134− mutex_lock(&mapping->i_mmap_mutex);
135− if (mapping_mapped(mapping)) {
136− mutex_unlock(&mapping->i_mmap_mutex);
137− percpu_up_write(&bdev->bd_block_size_semaphore);
138− return -EBUSY;
139− }
140− mutex_unlock(&mapping->i_mmap_mutex);
141−
142114 /* Don't change the size if it is same as current */
143115 if (bdev->bd_block_size != size) {
144116 sync_blockdev(bdev);
@@ -146,9 +118,6 @@ int set_blocksize(struct block_device *bdev, int size) · 1 unmodified line
146118 bdev->bd_inode->i_blkbits = blksize_bits(size);
147119 kill_bdev(bdev);
148120 }
149−
150− percpu_up_write(&bdev->bd_block_size_semaphore);
151−
152121 return 0;
153122 }
154123
@@ -181,52 +150,12 @@ static int · 26 unmodified lines
181150 blkdev_get_block(struct inode *inode, sector_t iblock,
182151 struct buffer_head *bh, int create)
183152 {
184− if (iblock >= blkdev_max_block(I_BDEV(inode))) {
185− if (create)
186− return -EIO;
187−
188− /*
189− * for reads, we're just trying to fill a partial page.
190− * return a hole, they will have to call get_block again
191− * before they can fill it, and they will get -EIO at that
192− * time
193− */
194− return 0;
195− }
196153 bh->b_bdev = I_BDEV(inode);
197154 bh->b_blocknr = iblock;
198155 set_buffer_mapped(bh);
199156 return 0;
200157 }
201158
202−static int
203−blkdev_get_blocks(struct inode *inode, sector_t iblock,
204− struct buffer_head *bh, int create)
205−{
206− sector_t end_block = blkdev_max_block(I_BDEV(inode));
207− unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
208−
209− if ((iblock + max_blocks) > end_block) {
210− max_blocks = end_block - iblock;
211− if ((long)max_blocks <= 0) {
212− if (create)
213− return -EIO; /* write fully beyond EOF */
214− /*
215− * It is a read which is fully beyond EOF. We return
216− * a !buffer_mapped buffer
217− */
218− max_blocks = 0;
219− }
220− }
221−
222− bh->b_bdev = I_BDEV(inode);
223− bh->b_blocknr = iblock;
224− bh->b_size = max_blocks << inode->i_blkbits;
225− if (max_blocks)
226− set_buffer_mapped(bh);
227− return 0;
228−}
229−
230159 static ssize_t
231160 blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
232161 loff_t offset, unsigned long nr_segs)
@@ -235,7 +164,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, · 2 unmodified lines
235164 struct inode *inode = file->f_mapping->host;
236165
237166 return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
238− nr_segs, blkdev_get_blocks, NULL, NULL, 0);
167+ nr_segs, blkdev_get_block, NULL, NULL, 0);
239168 }
240169
241170 int __sync_blockdev(struct block_device *bdev, int wait)
@@ -459,12 +388,6 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) · 217 unmodified lines
459388 struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);
460389 if (!ei)
461390 return NULL;
462−
463− if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) {
464− kmem_cache_free(bdev_cachep, ei);
465− return NULL;
466− }
467−
468391 return &ei->vfs_inode;
469392 }
470393
@@ -473,8 +396,6 @@ static void bdev_i_callback(struct rcu_head *head) · 2 unmodified lines
473396 struct inode *inode = container_of(head, struct inode, i_rcu);
474397 struct bdev_inode *bdi = BDEV_I(inode);
475398
476− percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore);
477−
478399 kmem_cache_free(bdev_cachep, bdi);
479400 }
480401
@@ -1593,22 +1514,6 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) · 1112 unmodified lines
15931514 return blkdev_ioctl(bdev, mode, cmd, arg);
15941515 }
15951516
1596−ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
1597− unsigned long nr_segs, loff_t pos)
1598−{
1599− ssize_t ret;
1600− struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
1601−
1602− percpu_down_read(&bdev->bd_block_size_semaphore);
1603−
1604− ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
1605−
1606− percpu_up_read(&bdev->bd_block_size_semaphore);
1607−
1608− return ret;
1609−}
1610−EXPORT_SYMBOL_GPL(blkdev_aio_read);
1611−
16121517 /*
16131518 * Write data to the block device. Only intended for the block device itself
16141519 * and the raw driver which basically is a fake block device.
@@ -1620,16 +1525,12 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, · 5 unmodified lines
16201525 unsigned long nr_segs, loff_t pos)
16211526 {
16221527 struct file *file = iocb->ki_filp;
1623− struct block_device *bdev = I_BDEV(file->f_mapping->host);
16241528 struct blk_plug plug;
16251529 ssize_t ret;
16261530
16271531 BUG_ON(iocb->ki_pos != pos);
16281532
16291533 blk_start_plug(&plug);
1630−
1631− percpu_down_read(&bdev->bd_block_size_semaphore);
1632−
16331534 ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
16341535 if (ret > 0 || ret == -EIOCBQUEUED) {
16351536 ssize_t err;
@@ -1638,62 +1539,11 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, · 2 unmodified lines
16381539 if (err < 0 && ret > 0)
16391540 ret = err;
16401541 }
1641−
1642− percpu_up_read(&bdev->bd_block_size_semaphore);
1643−
16441542 blk_finish_plug(&plug);
1645−
16461543 return ret;
16471544 }
16481545 EXPORT_SYMBOL_GPL(blkdev_aio_write);
16491546
1650−static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
1651−{
1652− int ret;
1653− struct block_device *bdev = I_BDEV(file->f_mapping->host);
1654−
1655− percpu_down_read(&bdev->bd_block_size_semaphore);
1656−
1657− ret = generic_file_mmap(file, vma);
1658−
1659− percpu_up_read(&bdev->bd_block_size_semaphore);
1660−
1661− return ret;
1662−}
1663−
1664−static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
1665− struct pipe_inode_info *pipe, size_t len,
1666− unsigned int flags)
1667−{
1668− ssize_t ret;
1669− struct block_device *bdev = I_BDEV(file->f_mapping->host);
1670−
1671− percpu_down_read(&bdev->bd_block_size_semaphore);
1672−
1673− ret = generic_file_splice_read(file, ppos, pipe, len, flags);
1674−
1675− percpu_up_read(&bdev->bd_block_size_semaphore);
1676−
1677− return ret;
1678−}
1679−
1680−static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
1681− struct file *file, loff_t *ppos, size_t len,
1682− unsigned int flags)
1683−{
1684− ssize_t ret;
1685− struct block_device *bdev = I_BDEV(file->f_mapping->host);
1686−
1687− percpu_down_read(&bdev->bd_block_size_semaphore);
1688−
1689− ret = generic_file_splice_write(pipe, file, ppos, len, flags);
1690−
1691− percpu_up_read(&bdev->bd_block_size_semaphore);
1692−
1693− return ret;
1694−}
1695−
1696−
16971547 /*
16981548 * Try to release a page associated with block device when the system
16991549 * is under memory pressure.
@@ -1724,16 +1574,16 @@ const struct file_operations def_blk_fops = { · 24 unmodified lines
17241574 .llseek = block_llseek,
17251575 .read = do_sync_read,
17261576 .write = do_sync_write,
1727− .aio_read = blkdev_aio_read,
1577+ .aio_read = generic_file_aio_read,
17281578 .aio_write = blkdev_aio_write,
1729− .mmap = blkdev_mmap,
1579+ .mmap = generic_file_mmap,
17301580 .fsync = blkdev_fsync,
17311581 .unlocked_ioctl = block_ioctl,
17321582 #ifdef CONFIG_COMPAT
17331583 .compat_ioctl = compat_blkdev_ioctl,
17341584 #endif
1735− .splice_read = blkdev_splice_read,
1736− .splice_write = blkdev_splice_write,
1585+ .splice_read = generic_file_splice_read,
1586+ .splice_write = generic_file_splice_write,
17371587 };
17381588
17391589 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
fs/buffer.c+61−32
@@ -911,6 +911,18 @@ link_dev_buffers(struct page *page, struct buffer_head *head) · 910 unmodified lines
911911 attach_page_buffers(page, head);
912912 }
913913
914+static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
915+{
916+ sector_t retval = ~((sector_t)0);
917+ loff_t sz = i_size_read(bdev->bd_inode);
918+
919+ if (sz) {
920+ unsigned int sizebits = blksize_bits(size);
921+ retval = (sz >> sizebits);
922+ }
923+ return retval;
924+}
925+
914926 /*
915927 * Initialise the state of a blockdev page's buffers.
916928 */
@@ -921,7 +933,7 @@ init_page_buffers(struct page *page, struct block_device *bdev, · 4 unmodified lines
921933 struct buffer_head *head = page_buffers(page);
922934 struct buffer_head *bh = head;
923935 int uptodate = PageUptodate(page);
924− sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode));
936+ sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size);
925937
926938 do {
927939 if (!buffer_mapped(bh)) {
@@ -1552,6 +1564,28 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block) · 624 unmodified lines
15521564 }
15531565 EXPORT_SYMBOL(unmap_underlying_metadata);
15541566
1567+/*
1568+ * Size is a power-of-two in the range 512..PAGE_SIZE,
1569+ * and the case we care about most is PAGE_SIZE.
1570+ *
1571+ * So this *could* possibly be written with those
1572+ * constraints in mind (relevant mostly if some
1573+ * architecture has a slow bit-scan instruction)
1574+ */
1575+static inline int block_size_bits(unsigned int blocksize)
1576+{
1577+ return ilog2(blocksize);
1578+}
1579+
1580+static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
1581+{
1582+ BUG_ON(!PageLocked(page));
1583+
1584+ if (!page_has_buffers(page))
1585+ create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits), b_state);
1586+ return page_buffers(page);
1587+}
1588+
15551589 /*
15561590 * NOTE! All mapped/uptodate combinations are valid:
15571591 *
@@ -1589,19 +1623,13 @@ static int __block_write_full_page(struct inode *inode, struct page *page, · 31 unmodified lines
15891623 sector_t block;
15901624 sector_t last_block;
15911625 struct buffer_head *bh, *head;
1592− const unsigned blocksize = 1 << inode->i_blkbits;
1626+ unsigned int blocksize, bbits;
15931627 int nr_underway = 0;
15941628 int write_op = (wbc->sync_mode == WB_SYNC_ALL ?
15951629 WRITE_SYNC : WRITE);
15961630
1597− BUG_ON(!PageLocked(page));
1598−
1599− last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
1600−
1601− if (!page_has_buffers(page)) {
1602− create_empty_buffers(page, blocksize,
1631+ head = create_page_buffers(page, inode,
16031632 (1 << BH_Dirty)|(1 << BH_Uptodate));
1604− }
16051633
16061634 /*
16071635 * Be very careful. We have no exclusion from __set_page_dirty_buffers
@@ -1613,9 +1641,12 @@ static int __block_write_full_page(struct inode *inode, struct page *page, · 5 unmodified lines
16131641 * handle that here by just cleaning them.
16141642 */
16151643
1616− block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
1617− head = page_buffers(page);
16181644 bh = head;
1645+ blocksize = bh->b_size;
1646+ bbits = block_size_bits(blocksize);
1647+
1648+ block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
1649+ last_block = (i_size_read(inode) - 1) >> bbits;
16191650
16201651 /*
16211652 * Get all the dirty buffers mapped to disk addresses and
@@ -1806,12 +1837,10 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, · 184 unmodified lines
18061837 BUG_ON(to > PAGE_CACHE_SIZE);
18071838 BUG_ON(from > to);
18081839
1809− blocksize = 1 << inode->i_blkbits;
1810− if (!page_has_buffers(page))
1811− create_empty_buffers(page, blocksize, 0);
1812− head = page_buffers(page);
1840+ head = create_page_buffers(page, inode, 0);
1841+ blocksize = head->b_size;
1842+ bbits = block_size_bits(blocksize);
18131843
1814− bbits = inode->i_blkbits;
18151844 block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
18161845
18171846 for(bh = head, block_start = 0; bh != head || !block_start;
@@ -1881,11 +1910,11 @@ static int __block_commit_write(struct inode *inode, struct page *page, · 63 unmodified lines
18811910 unsigned blocksize;
18821911 struct buffer_head *bh, *head;
18831912
1884− blocksize = 1 << inode->i_blkbits;
1913+ bh = head = page_buffers(page);
1914+ blocksize = bh->b_size;
18851915
1886− for(bh = head = page_buffers(page), block_start = 0;
1887− bh != head || !block_start;
1888− block_start=block_end, bh = bh->b_this_page) {
1916+ block_start = 0;
1917+ do {
18891918 block_end = block_start + blocksize;
18901919 if (block_end <= from || block_start >= to) {
18911920 if (!buffer_uptodate(bh))
@@ -1895,7 +1924,10 @@ static int __block_commit_write(struct inode *inode, struct page *page, · 3 unmodified lines
18951924 mark_buffer_dirty(bh);
18961925 }
18971926 clear_buffer_new(bh);
1898− }
1927+
1928+ block_start = block_end;
1929+ bh = bh->b_this_page;
1930+ } while (bh != head);
18991931
19001932 /*
19011933 * If this is a partial write which happened to make all buffers
@@ -2020,7 +2052,6 @@ EXPORT_SYMBOL(generic_write_end); · 118 unmodified lines
20202052 int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
20212053 unsigned long from)
20222054 {
2023− struct inode *inode = page->mapping->host;
20242055 unsigned block_start, block_end, blocksize;
20252056 unsigned to;
20262057 struct buffer_head *bh, *head;
@@ -2029,13 +2060,13 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, · 2 unmodified lines
20292060 if (!page_has_buffers(page))
20302061 return 0;
20312062
2032− blocksize = 1 << inode->i_blkbits;
2063+ head = page_buffers(page);
2064+ blocksize = head->b_size;
20332065 to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count);
20342066 to = from + to;
20352067 if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)
20362068 return 0;
20372069
2038− head = page_buffers(page);
20392070 bh = head;
20402071 block_start = 0;
20412072 do {
@@ -2068,18 +2099,16 @@ int block_read_full_page(struct page *page, get_block_t *get_block) · 26 unmodified lines
20682099 struct inode *inode = page->mapping->host;
20692100 sector_t iblock, lblock;
20702101 struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
2071− unsigned int blocksize;
2102+ unsigned int blocksize, bbits;
20722103 int nr, i;
20732104 int fully_mapped = 1;
20742105
2075− BUG_ON(!PageLocked(page));
2076− blocksize = 1 << inode->i_blkbits;
2077− if (!page_has_buffers(page))
2078− create_empty_buffers(page, blocksize, 0);
2079− head = page_buffers(page);
2106+ head = create_page_buffers(page, inode, 0);
2107+ blocksize = head->b_size;
2108+ bbits = block_size_bits(blocksize);
20802109
2081− iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
2082− lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits;
2110+ iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
2111+ lblock = (i_size_read(inode)+blocksize-1) >> bbits;
20832112 bh = head;
20842113 nr = 0;
20852114 i = 0;
fs/direct-io.c+5−3
@@ -540,6 +540,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, · 539 unmodified lines
540540 sector_t fs_endblk; /* Into file, in filesystem-sized blocks */
541541 unsigned long fs_count; /* Number of filesystem-sized blocks */
542542 int create;
543+ unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
543544
544545 /*
545546 * If there was a memory error and we've overwritten all the
@@ -554,7 +555,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, · 8 unmodified lines
554555 fs_count = fs_endblk - fs_startblk + 1;
555556
556557 map_bh->b_state = 0;
557− map_bh->b_size = fs_count << dio->inode->i_blkbits;
558+ map_bh->b_size = fs_count << i_blkbits;
558559
559560 /*
560561 * For writes inside i_size on a DIO_SKIP_HOLES filesystem we
@@ -1053,7 +1054,8 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, · 492 unmodified lines
10531054 int seg;
10541055 size_t size;
10551056 unsigned long addr;
1056− unsigned blkbits = inode->i_blkbits;
1057+ unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
1058+ unsigned blkbits = i_blkbits;
10571059 unsigned blocksize_mask = (1 << blkbits) - 1;
10581060 ssize_t retval = -EINVAL;
10591061 loff_t end = offset;
@@ -1149,7 +1151,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, · 89 unmodified lines
11491151 dio->inode = inode;
11501152 dio->rw = rw;
11511153 sdio.blkbits = blkbits;
1152− sdio.blkfactor = inode->i_blkbits - blkbits;
1154+ sdio.blkfactor = i_blkbits - blkbits;
11531155 sdio.block_in_file = offset >> blkbits;
11541156
11551157 sdio.get_block = get_block;
include/linux/fs.h+0−5
@@ -462,8 +462,6 @@ struct block_device { · 461 unmodified lines
462462 int bd_fsfreeze_count;
463463 /* Mutex for freeze */
464464 struct mutex bd_fsfreeze_mutex;
465− /* A semaphore that prevents I/O while block size is being changed */
466− struct percpu_rw_semaphore bd_block_size_semaphore;
467465 };
468466
469467 /*
@@ -2049,7 +2047,6 @@ extern void unregister_blkdev(unsigned int, const char *); · 1579 unmodified lines
20492047 extern struct block_device *bdget(dev_t);
20502048 extern struct block_device *bdgrab(struct block_device *bdev);
20512049 extern void bd_set_size(struct block_device *, loff_t size);
2052−extern sector_t blkdev_max_block(struct block_device *bdev);
20532050 extern void bd_forget(struct inode *inode);
20542051 extern void bdput(struct block_device *);
20552052 extern void invalidate_bdev(struct block_device *);
@@ -2379,8 +2376,6 @@ extern int generic_segment_checks(const struct iovec *iov, · 323 unmodified lines
23792376 unsigned long *nr_segs, size_t *count, int access_flags);
23802377
23812378 /* fs/block_dev.c */
2382−extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
2383− unsigned long nr_segs, loff_t pos);
23842379 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
23852380 unsigned long nr_segs, loff_t pos);
23862381 extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,