Whamcloud - gitweb
b=4336
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-o_direct-1.patch
1 --- 2.4.20-pre2/fs/ext3/inode.c~ext3-o_direct   Thu Aug 15 01:11:02 2002
2 +++ 2.4.20-pre2-akpm/fs/ext3/inode.c    Thu Aug 15 01:25:55 2002
3 @@ -27,6 +27,7 @@
4  #include <linux/ext3_jbd.h>
5  #include <linux/jbd.h>
6  #include <linux/locks.h>
7 +#include <linux/iobuf.h>
8  #include <linux/smp_lock.h>
9  #include <linux/highuid.h>
10  #include <linux/quotaops.h>
11 @@ -716,9 +717,9 @@ err_out:
12   * The BKL may not be held on entry here.  Be sure to take it early.
13   */
14  
15 -static int ext3_get_block_handle(handle_t *handle, struct inode *inode, 
16 -                                long iblock,
17 -                                struct buffer_head *bh_result, int create)
18 +static int
19 +ext3_get_block_handle(handle_t *handle, struct inode *inode, long iblock,
20 +               struct buffer_head *bh_result, int create, int extend_disksize)
21  {
22         int err = -EIO;
23         int offsets[4];
24 @@ -798,16 +799,18 @@ out:
25         if (err)
26                 goto cleanup;
27  
28 -       new_size = inode->i_size;
29 -       /*
30 -        * This is not racy against ext3_truncate's modification of i_disksize
31 -        * because VM/VFS ensures that the file cannot be extended while
32 -        * truncate is in progress.  It is racy between multiple parallel
33 -        * instances of get_block, but we have the BKL.
34 -        */
35 -       if (new_size > inode->u.ext3_i.i_disksize)
36 -               inode->u.ext3_i.i_disksize = new_size;
37 -
38 +       if (extend_disksize) {
39 +               /*
40 +                * This is not racy against ext3_truncate's modification of
41 +                * i_disksize because VM/VFS ensures that the file cannot be
42 +                * extended while truncate is in progress.  It is racy between
43 +                * multiple parallel instances of get_block, but we have BKL.
44 +                */
45 +               struct ext3_inode_info *ei = EXT3_I(inode);
46 +               new_size = inode->i_size;
47 +               if (new_size > ei->i_disksize)
48 +                       ei->i_disksize = new_size;
49 +       }
50         bh_result->b_state |= (1UL << BH_New);
51         goto got_it;
52  
53 @@ -834,7 +837,38 @@ static int ext3_get_block(struct inode *
54                 handle = ext3_journal_current_handle();
55                 J_ASSERT(handle != 0);
56         }
57 -       ret = ext3_get_block_handle(handle, inode, iblock, bh_result, create);
58 +       ret = ext3_get_block_handle(handle, inode, iblock,
59 +                               bh_result, create, 1);
60 +       return ret;
61 +}
62 +
63 +#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
64 +
65 +static int
66 +ext3_direct_io_get_block(struct inode *inode, long iblock,
67 +               struct buffer_head *bh_result, int create)
68 +{
69 +       handle_t *handle = journal_current_handle();
70 +       int ret = 0;
71 +
72 +       lock_kernel();
73 +       if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
74 +               /*
75 +                * Getting low on buffer credits...
76 +                */
77 +               if (!ext3_journal_extend(handle, DIO_CREDITS)) {
78 +                       /*
79 +                        * Couldn't extend the transaction.  Start a new one
80 +                        */
81 +                       ret = ext3_journal_restart(handle, DIO_CREDITS);
82 +               }
83 +       }
84 +       if (ret == 0)
85 +               ret = ext3_get_block_handle(handle, inode, iblock,
86 +                                       bh_result, create, 0);
87 +       if (ret == 0)
88 +               bh_result->b_size = (1 << inode->i_blkbits);
89 +       unlock_kernel();
90         return ret;
91  }
92  
93 @@ -852,7 +886,7 @@ struct buffer_head *ext3_getblk(handle_t
94         dummy.b_state = 0;
95         dummy.b_blocknr = -1000;
96         buffer_trace_init(&dummy.b_history);
97 -       *errp = ext3_get_block_handle(handle, inode, block, &dummy, create);
98 +       *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1);
99         if (!*errp && buffer_mapped(&dummy)) {
100                 struct buffer_head *bh;
101                 bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
102 @@ -1349,6 +1383,67 @@ static int ext3_releasepage(struct page 
103         return journal_try_to_free_buffers(journal, page, wait);
104  }
105  
106 +static int
107 +ext3_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf,
108 +               unsigned long blocknr, int blocksize)
109 +{
110 +       struct ext3_inode_info *ei = EXT3_I(inode);
111 +       handle_t *handle = NULL;
112 +       int ret;
113 +       int orphan = 0;
114 +       loff_t offset = blocknr << inode->i_blkbits;    /* ugh */
115 +       ssize_t count = iobuf->length;                  /* ditto */
116 +
117 +       if (rw == WRITE) {
118 +               loff_t final_size = offset + count;
119 +
120 +               lock_kernel();
121 +               handle = ext3_journal_start(inode, DIO_CREDITS);
122 +               unlock_kernel();
123 +               if (IS_ERR(handle)) {
124 +                       ret = PTR_ERR(handle);
125 +                       goto out;
126 +               }
127 +               if (final_size > inode->i_size) {
128 +                       lock_kernel();
129 +                       ret = ext3_orphan_add(handle, inode);
130 +                       unlock_kernel();
131 +                       if (ret)
132 +                               goto out_stop;
133 +                       orphan = 1;
134 +                       ei->i_disksize = inode->i_size;
135 +               }
136 +       }
137 +
138 +       ret = generic_direct_IO(rw, inode, iobuf, blocknr,
139 +                               blocksize, ext3_direct_io_get_block);
140 +
141 +out_stop:
142 +       if (handle) {
143 +               int err;
144 +
145 +               lock_kernel();
146 +               if (orphan) 
147 +                       ext3_orphan_del(handle, inode);
148 +               if (orphan && ret > 0) {
149 +                       loff_t end = offset + ret;
150 +                       if (end > inode->i_size) {
151 +                               ei->i_disksize = end;
152 +                               inode->i_size = end;
153 +                               err = ext3_mark_inode_dirty(handle, inode);
154 +                               if (!ret) 
155 +                                       ret = err;
156 +                       }
157 +               }
158 +               err = ext3_journal_stop(handle, inode);
159 +               if (ret == 0)
160 +                       ret = err;
161 +               unlock_kernel();
162 +       }
163 +out:
164 +       return ret;
165 +
166 +}
167  
168  struct address_space_operations ext3_aops = {
169         readpage:       ext3_readpage,          /* BKL not held.  Don't need */
170 @@ -1359,6 +1454,7 @@ struct address_space_operations ext3_aop
171         bmap:           ext3_bmap,              /* BKL held */
172         flushpage:      ext3_flushpage,         /* BKL not held.  Don't need */
173         releasepage:    ext3_releasepage,       /* BKL not held.  Don't need */
174 +       direct_IO:      ext3_direct_IO,         /* BKL not held.  Don't need */
175  };
176  
177  /*