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