Whamcloud - gitweb
63f4463b04557f24f2b1a8c9c7a764a252837616
[fs/lustre-release.git] / lustre / kernel_patches / patches / extN-noread.patch
1  fs/ext3/ialloc.c        |   47 +++++++++++++++++++++-
2  fs/ext3/inode.c         |   99 ++++++++++++++++++++++++++++++++++++------------
3  include/linux/ext3_fs.h |    2 
4  3 files changed, 122 insertions(+), 26 deletions(-)
5
6 --- linux-2.4.18-chaos52/fs/ext3/ialloc.c~extN-noread   2003-05-16 12:26:29.000000000 +0800
7 +++ linux-2.4.18-chaos52-root/fs/ext3/ialloc.c  2003-05-16 12:26:31.000000000 +0800
8 @@ -289,6 +289,37 @@ error_return:
9  }
10  
11  /*
12 + * @block_group: block group of inode
13 + * @offset: relative offset of inode within @block_group
14 + *
15 + * Check whether any of the inodes in this disk block are in use.
16 + *
17 + * Caller must be holding superblock lock (group/bitmap read lock in future).
18 + */
19 +int ext3_itable_block_used(struct super_block *sb, unsigned int block_group,
20 +                          int offset)
21 +{
22 +       int bitmap_nr = load_inode_bitmap(sb, block_group);
23 +       int inodes_per_block;
24 +       unsigned long inum, iend;
25 +       struct buffer_head *ibitmap;
26 +
27 +       if (bitmap_nr < 0)
28 +               return 1;
29 +
30 +       inodes_per_block = sb->s_blocksize / EXT3_SB(sb)->s_inode_size;
31 +       inum = offset & ~(inodes_per_block - 1);
32 +       iend = inum + inodes_per_block;
33 +       ibitmap = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
34 +       for (; inum < iend; inum++) {
35 +               if (inum != offset && ext3_test_bit(inum, ibitmap->b_data))
36 +                       return 1;
37 +       }
38 +
39 +       return 0;
40 +}
41 +
42 +/*
43   * There are two policies for allocating an inode.  If the new inode is
44   * a directory, then a forward search is made for a block group with both
45   * free space and a low directory-to-inode ratio; if that fails, then of
46 @@ -312,6 +343,7 @@ struct inode * ext3_new_inode (handle_t 
47         struct ext3_group_desc * gdp;
48         struct ext3_group_desc * tmp;
49         struct ext3_super_block * es;
50 +       struct ext3_iloc iloc;
51         int err = 0;
52  
53         /* Cannot create files in a deleted directory */
54 @@ -505,7 +537,7 @@ repeat:
55         ei->i_prealloc_count = 0;
56  #endif
57         ei->i_block_group = i;
58 -       
59 +
60         if (ei->i_flags & EXT3_SYNC_FL)
61                 inode->i_flags |= S_SYNC;
62         if (IS_SYNC(inode))
63 @@ -514,9 +546,18 @@ repeat:
64         inode->i_generation = sbi->s_next_generation++;
65  
66         ei->i_state = EXT3_STATE_NEW;
67 -       err = ext3_mark_inode_dirty(handle, inode);
68 +       err = ext3_get_inode_loc_new(inode, &iloc, 1);
69         if (err) goto fail;
70 -       
71 +       BUFFER_TRACE(iloc->bh, "get_write_access");
72 +       err = ext3_journal_get_write_access(handle, iloc.bh);
73 +       if (err) {
74 +               brelse(iloc.bh);
75 +               iloc.bh = NULL;
76 +               goto fail;
77 +       }
78 +       err = ext3_mark_iloc_dirty(handle, inode, &iloc);
79 +       if (err) goto fail;
80 +
81         unlock_super (sb);
82         if(DQUOT_ALLOC_INODE(inode)) {
83                 DQUOT_DROP(inode);
84 --- linux-2.4.18-chaos52/fs/ext3/inode.c~extN-noread    2003-05-16 12:26:29.000000000 +0800
85 +++ linux-2.4.18-chaos52-root/fs/ext3/inode.c   2003-05-16 12:27:06.000000000 +0800
86 @@ -2011,23 +2011,28 @@ out_stop:
87         ext3_journal_stop(handle, inode);
88  }
89  
90 -/* 
91 - * ext3_get_inode_loc returns with an extra refcount against the
92 - * inode's underlying buffer_head on success. 
93 - */
94 +#define NUM_INODE_PREREAD      16
95  
96 -int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
97 +/*
98 + * ext3_get_inode_loc returns with an extra refcount against the inode's
99 + * underlying buffer_head on success.  If this is for a new inode allocation
100 + * (new is non-zero) then we may be able to optimize away the read if there
101 + * are no other in-use inodes in this inode table block.  If we need to do
102 + * a read, then read in a whole chunk of blocks to avoid blocking again soon
103 + * if we are doing lots of creates/updates.
104 + */
105 +int ext3_get_inode_loc_new(struct inode *inode, struct ext3_iloc *iloc, int new)
106  {
107         struct super_block *sb = inode->i_sb;
108         struct ext3_sb_info *sbi = EXT3_SB(sb);
109 -       struct buffer_head *bh = 0;
110 +       struct buffer_head *bh[NUM_INODE_PREREAD];
111         unsigned long block;
112         unsigned long block_group;
113         unsigned long group_desc;
114         unsigned long desc;
115         unsigned long offset;
116         struct ext3_group_desc * gdp;
117 -               
118 +
119         if ((inode->i_ino != EXT3_ROOT_INO &&
120                 inode->i_ino != EXT3_JOURNAL_INO &&
121                 inode->i_ino < EXT3_FIRST_INO(sb)) ||
122 @@ -2042,38 +2047,86 @@ int ext3_get_inode_loc (struct inode *in
123         }
124         group_desc = block_group >> sbi->s_desc_per_block_bits;
125         desc = block_group & (sbi->s_desc_per_block - 1);
126 -       bh = sbi->s_group_desc[group_desc];
127 -       if (!bh) {
128 +       if (!sbi->s_group_desc[group_desc]) {
129                 ext3_error(sb, __FUNCTION__, "Descriptor not loaded");
130                 goto bad_inode;
131         }
132  
133 -       gdp = (struct ext3_group_desc *) bh->b_data;
134 +       gdp = (struct ext3_group_desc *)(sbi->s_group_desc[group_desc]->b_data);
135 +
136         /*
137          * Figure out the offset within the block group inode table
138          */
139 -       offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) *
140 -               sbi->s_inode_size;
141 +       offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group);
142 +
143         block = le32_to_cpu(gdp[desc].bg_inode_table) +
144 -               (offset >> EXT3_BLOCK_SIZE_BITS(sb));
145 -       if (!(bh = sb_bread(sb, block))) {
146 -               ext3_error (sb, __FUNCTION__,
147 -                           "unable to read inode block - "
148 -                           "inode=%lu, block=%lu", inode->i_ino, block);
149 -               goto bad_inode;
150 +               (offset * sbi->s_inode_size >> EXT3_BLOCK_SIZE_BITS(sb));
151 +
152 +       bh[0] = sb_getblk(sb, block);
153 +       if (buffer_uptodate(bh[0]))
154 +               goto done;
155 +
156 +       /* If we don't really need to read this block, and it isn't already
157 +        * in memory, then we just zero it out.  Otherwise, we keep the
158 +        * current block contents (deleted inode data) for posterity.
159 +        */
160 +       if (new && !ext3_itable_block_used(sb, block_group, offset)) {
161 +               lock_buffer(bh[0]);
162 +               memset(bh[0]->b_data, 0, bh[0]->b_size);
163 +               mark_buffer_uptodate(bh[0], 1);
164 +               unlock_buffer(bh[0]);
165 +       } else {
166 +               unsigned long block_end, itable_end;
167 +               int count = 1;
168 +
169 +               itable_end = le32_to_cpu(gdp[desc].bg_inode_table) +
170 +                               sbi->s_itb_per_group;
171 +               block_end = block + NUM_INODE_PREREAD;
172 +               if (block_end > itable_end)
173 +                       block_end = itable_end;
174 +
175 +               for (++block; block < block_end; block++) {
176 +                       bh[count] = sb_getblk(sb, block);
177 +                       if (count && (buffer_uptodate(bh[count]) ||
178 +                                     buffer_locked(bh[count]))) {
179 +                               __brelse(bh[count]);
180 +                       } else
181 +                               count++;
182 +               }
183 +
184 +               ll_rw_block(READ, count, bh);
185 +
186 +               /* Release all but the block we actually need (bh[0]) */
187 +               while (--count > 0)
188 +                       __brelse(bh[count]);
189 +
190 +               wait_on_buffer(bh[0]);
191 +               if (!buffer_uptodate(bh[0])) {
192 +                       ext3_error(sb, __FUNCTION__,
193 +                                  "unable to read inode block - "
194 +                                  "inode=%lu, block=%lu", inode->i_ino,
195 +                                  bh[0]->b_blocknr);
196 +                       goto bad_inode;
197 +               }
198         }
199 -       offset &= (EXT3_BLOCK_SIZE(sb) - 1);
200 + done:
201 +       offset = (offset * sbi->s_inode_size) & (EXT3_BLOCK_SIZE(sb) - 1);
202  
203 -       iloc->bh = bh;
204 -       iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
205 +       iloc->bh = bh[0];
206 +       iloc->raw_inode = (struct ext3_inode *)(bh[0]->b_data + offset);
207         iloc->block_group = block_group;
208 -       
209 +
210         return 0;
211 -       
212 +
213   bad_inode:
214         return -EIO;
215  }
216  
217 +int ext3_get_inode_loc(struct inode *inode, struct ext3_iloc *iloc)
218 +{
219 +       return ext3_get_inode_loc_new(inode, iloc, 0);
220 +}
221 +
222  void ext3_read_inode(struct inode * inode)
223  {
224         struct ext3_iloc iloc;
225 --- linux-2.4.18-chaos52/include/linux/ext3_fs.h~extN-noread    2003-05-16 12:26:29.000000000 +0800
226 +++ linux-2.4.18-chaos52-root/include/linux/ext3_fs.h   2003-05-16 12:26:31.000000000 +0800
227 @@ -640,6 +640,8 @@ extern int ext3_forget(handle_t *, int, 
228  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
229  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
230  
231 +extern int ext3_itable_block_used(struct super_block *sb, unsigned int, int);
232 +extern int ext3_get_inode_loc_new(struct inode *, struct ext3_iloc *, int);
233  extern int  ext3_get_inode_loc (struct inode *, struct ext3_iloc *);
234  extern void ext3_read_inode (struct inode *);
235  extern void ext3_write_inode (struct inode *, int);
236
237 _