2 Index: linux-2.4.20-rh/fs/ext3/inode.c
3 ===================================================================
4 --- linux-2.4.20-rh.orig/fs/ext3/inode.c 2003-09-04 18:01:41.000000000 +0800
5 +++ linux-2.4.20-rh/fs/ext3/inode.c 2003-09-04 18:18:54.000000000 +0800
7 #include <linux/ext3_jbd.h>
9 #include <linux/locks.h>
10 +#include <linux/iobuf.h>
11 #include <linux/smp_lock.h>
12 #include <linux/highuid.h>
13 #include <linux/quotaops.h>
15 * The BKL may not be held on entry here. Be sure to take it early.
18 -static int ext3_get_block_handle(handle_t *handle, struct inode *inode,
20 - struct buffer_head *bh_result, int create)
22 +ext3_get_block_handle(handle_t *handle, struct inode *inode, long iblock,
23 + struct buffer_head *bh_result, int create, int extend_disksize)
31 - new_size = inode->i_size;
33 - * This is not racy against ext3_truncate's modification of i_disksize
34 - * because VM/VFS ensures that the file cannot be extended while
35 - * truncate is in progress. It is racy between multiple parallel
36 - * instances of get_block, but we have the BKL.
38 - if (new_size > inode->u.ext3_i.i_disksize)
39 - inode->u.ext3_i.i_disksize = new_size;
40 + if (extend_disksize) {
42 + * This is not racy against ext3_truncate's modification of
43 + * i_disksize because VM/VFS ensures that the file cannot be
44 + * extended while truncate is in progress. It is racy between
45 + * multiple parallel instances of get_block, but we have BKL.
47 + struct ext3_inode_info *ei = EXT3_I(inode);
48 + new_size = inode->i_size;
49 + if (new_size > ei->i_disksize)
50 + ei->i_disksize = new_size;
53 bh_result->b_state |= (1UL << BH_New);
56 handle = ext3_journal_current_handle();
57 J_ASSERT(handle != 0);
59 - ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create);
60 + ret = ext3_get_block_handle(handle, inode, iblock,
61 + bh_result, create, 1);
65 +#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
68 +ext3_direct_io_get_block(struct inode *inode, long iblock,
69 + struct buffer_head *bh_result, int create)
71 + handle_t *handle = journal_current_handle();
75 + if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
77 + * Getting low on buffer credits...
79 + if (!ext3_journal_extend(handle, DIO_CREDITS)) {
81 + * Couldn't extend the transaction. Start a new one
83 + ret = ext3_journal_restart(handle, DIO_CREDITS);
87 + ret = ext3_get_block_handle(handle, inode, iblock,
88 + bh_result, create, 0);
90 + bh_result->b_size = (1 << inode->i_blkbits);
97 dummy.b_blocknr = -1000;
98 buffer_trace_init(&dummy.b_history);
99 - *errp = ext3_get_block_handle(handle, inode, block, &dummy, create);
100 + *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
101 if (!*errp && buffer_mapped(&dummy)) {
102 struct buffer_head *bh;
103 bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
104 @@ -1387,6 +1422,67 @@
105 return journal_try_to_free_buffers(journal, page, wait);
109 +ext3_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf,
110 + unsigned long blocknr, int blocksize)
112 + struct ext3_inode_info *ei = EXT3_I(inode);
113 + handle_t *handle = NULL;
116 + loff_t offset = blocknr << inode->i_blkbits; /* ugh */
117 + ssize_t count = iobuf->length; /* ditto */
120 + loff_t final_size = offset + count;
123 + handle = ext3_journal_start(inode, DIO_CREDITS);
125 + if (IS_ERR(handle)) {
126 + ret = PTR_ERR(handle);
129 + if (final_size > inode->i_size) {
131 + ret = ext3_orphan_add(handle, inode);
136 + ei->i_disksize = inode->i_size;
140 + ret = generic_direct_IO(rw, inode, iobuf, blocknr,
141 + blocksize, ext3_direct_io_get_block);
149 + ext3_orphan_del(handle, inode);
150 + if (orphan && ret > 0) {
151 + loff_t end = offset + ret;
152 + if (end > inode->i_size) {
153 + ei->i_disksize = end;
154 + inode->i_size = end;
155 + err = ext3_mark_inode_dirty(handle, inode);
160 + err = ext3_journal_stop(handle, inode);
170 struct address_space_operations ext3_aops = {
171 readpage: ext3_readpage, /* BKL not held. Don't need */
172 @@ -1397,6 +1493,7 @@
173 bmap: ext3_bmap, /* BKL held */
174 flushpage: ext3_flushpage, /* BKL not held. Don't need */
175 releasepage: ext3_releasepage, /* BKL not held. Don't need */
176 + direct_IO: ext3_direct_IO, /* BKL not held. Don't need */
180 @@ -2970,7 +3067,7 @@
181 /* alloc blocks one by one */
182 for (i = 0; i < nblocks; i++) {
183 ret = ext3_get_block_handle(handle, inode, blocks[i],
189 @@ -3030,7 +3127,7 @@
193 - rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1);
194 + rc = ext3_get_block_handle(handle, inode, iblock, &bh, 1, 1);
196 printk(KERN_INFO "ext3_map_inode_page: error %d "
197 "allocating block %ld\n", rc, iblock);