Whamcloud - gitweb
file configurable-x86-stack-2.4.22-rh.patch was initially added on branch b_devel.
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-noread-inode.patch
1
2 ext3_get_inode_loc() read inode's block only if:
3   1) this inode has no copy in memory
4   2) inode's block has another valid inode(s)
5
6 this optimization allows to avoid needless I/O in two cases:
7 1) just allocated inode is first valid in the inode's block
8 2) kernel wants to write inode, but buffer in which inode
9    belongs to gets freed by VM
10
11
12
13
14 diff -puN fs/ext3/inode.c~ext3-noread-inode fs/ext3/inode.c
15 --- linux-2.5.73/fs/ext3/inode.c~ext3-noread-inode      Thu Jul 10 12:03:52 2003
16 +++ linux-2.5.73-alexey/fs/ext3/inode.c Thu Jul 10 15:52:59 2003
17 @@ -2286,7 +2286,7 @@ out_stop:
18   * inode's underlying buffer_head on success. 
19   */
20  
21 -int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
22 +int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc, int in_mem)
23  {
24         struct buffer_head *bh = 0;
25         unsigned long block;
26 @@ -2328,12 +2328,88 @@ int ext3_get_inode_loc (struct inode *in
27                 EXT3_INODE_SIZE(inode->i_sb);
28         block = le32_to_cpu(gdp[desc].bg_inode_table) +
29                 (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
30 -       if (!(bh = sb_bread(inode->i_sb, block))) {
31 +       if (!(bh = sb_getblk(inode->i_sb, block))) {
32                 ext3_error (inode->i_sb, "ext3_get_inode_loc",
33                             "unable to read inode block - "
34                             "inode=%lu, block=%lu", inode->i_ino, block);
35                 goto bad_inode;
36         }
37 +       if (!buffer_uptodate(bh)) {
38 +               lock_buffer(bh);
39 +               if (buffer_uptodate(bh)) {
40 +                       /* someone has already initialized buffer */
41 +                       unlock_buffer(bh);
42 +                       goto has_buffer;
43 +               }
44 +
45 +               /* we can't skip I/O if inode is on a disk only */
46 +               if (in_mem) {
47 +                       struct buffer_head *bitmap_bh; 
48 +                       struct ext3_group_desc *desc;
49 +                       int inodes_per_buffer;
50 +                       int inode_offset, i;
51 +                       int start;
52 +
53 +                       /*
54 +                        * if this inode is only valid in buffer we need not I/O
55 +                        */
56 +                       inodes_per_buffer = bh->b_size /
57 +                               EXT3_INODE_SIZE(inode->i_sb);
58 +                       inode_offset = ((inode->i_ino - 1) %
59 +                                       EXT3_INODES_PER_GROUP(inode->i_sb));
60 +                       start = inode_offset & ~(inodes_per_buffer - 1);
61 +
62 +                       /* check is inode bitmap is in cache? */
63 +                       desc = ext3_get_group_desc(inode->i_sb, block_group, NULL);
64 +                       if (!desc)
65 +                               goto make_io;
66 +
67 +                       bitmap_bh = sb_getblk(inode->i_sb, le32_to_cpu(desc->bg_inode_bitmap));
68 +                       if (!bitmap_bh)
69 +                               goto make_io;
70 +
71 +                       /* 
72 +                        * if inode bitmap isn't in cache then we may end up by 2 reads
73 +                        * instead of 1 read before optimizing. skip it
74 +                        */
75 +                       if (!buffer_uptodate(bitmap_bh)) {
76 +                               brelse(bitmap_bh);
77 +                               goto make_io;
78 +                       }
79 +                       for (i = start; i < start + inodes_per_buffer; i++) {
80 +                               if (i == inode_offset)
81 +                                       continue;
82 +                               if (ext3_test_bit(i, bitmap_bh->b_data))
83 +                                       break;
84 +                       }
85 +                       brelse(bitmap_bh);
86 +                       if (i == start + inodes_per_buffer) {
87 +                               /* all inodes (but our) are free. so, we skip I/O */
88 +                               memset(bh->b_data, 0, bh->b_size);
89 +                               set_buffer_uptodate(bh);
90 +                               unlock_buffer(bh);
91 +                               goto has_buffer;
92 +                       }
93 +               }
94 +
95 +make_io:
96 +               /*
97 +                * No, there are another valid inodes in the buffer
98 +                * so, to preserve them we have to read buffer from
99 +                * the disk
100 +                */
101 +               get_bh(bh);
102 +               bh->b_end_io = end_buffer_io_sync;
103 +               submit_bh(READ, bh);
104 +               wait_on_buffer(bh);
105 +               if (!buffer_uptodate(bh)) {
106 +                       ext3_error (inode->i_sb, "ext3_get_inode_loc",
107 +                                       "unable to read inode block - "
108 +                                       "inode=%lu, block=%lu", inode->i_ino, block);
109 +                       goto bad_inode;
110 +               }
111 +       }
112 +  has_buffer:
113         offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
114  
115         iloc->bh = bh;
116 @@ -2376,7 +2452,7 @@ void ext3_read_inode(struct inode * inod
117  endif
118         if (ext3_iopen_get_inode(inode))
119                 return;
120 -       if (ext3_get_inode_loc(inode, &iloc))
121 +       if (ext3_get_inode_loc(inode, &iloc, 0))
122                 goto bad_inode;
123         bh = iloc.bh;
124         raw_inode = iloc.raw_inode;
125 @@ -2781,7 +2857,7 @@ ext3_reserve_inode_write(handle_t *handl
126  {
127         int err = 0;
128         if (handle) {
129 -               err = ext3_get_inode_loc(inode, iloc);
130 +               err = ext3_get_inode_loc(inode, iloc, 1);
131                 if (!err) {
132                         BUFFER_TRACE(iloc->bh, "get_write_access");
133                         err = ext3_journal_get_write_access(handle, iloc->bh);
134 @@ -2879,7 +2955,7 @@ ext3_pin_inode(handle_t *handle, struct 
135  
136         int err = 0;
137         if (handle) {
138 -               err = ext3_get_inode_loc(inode, &iloc);
139 +               err = ext3_get_inode_loc(inode, &iloc, 1);
140                 if (!err) {
141                         BUFFER_TRACE(iloc.bh, "get_write_access");
142                         err = journal_get_write_access(handle, iloc.bh);
143 diff -puN fs/ext3/ialloc.c~ext3-noread-inode fs/ext3/ialloc.c
144 --- linux-2.5.73/fs/ext3/ialloc.c~ext3-noread-inode     Thu Jul 10 13:05:37 2003
145 +++ linux-2.5.73-alexey/fs/ext3/ialloc.c        Thu Jul 10 13:06:12 2003
146 @@ -50,7 +50,7 @@
147   *
148   * Return buffer_head of bitmap on success or NULL.
149   */
150 -static struct buffer_head *
151 +struct buffer_head *
152  read_inode_bitmap(struct super_block * sb, unsigned long block_group)
153  {
154         struct ext3_group_desc *desc;
155 diff -puN include/linux/ext3_fs.h~ext3-noread-inode include/linux/ext3_fs.h
156 --- linux-2.5.73/include/linux/ext3_fs.h~ext3-noread-inode      Thu Jul 10 13:41:59 2003
157 +++ linux-2.5.73-alexey/include/linux/ext3_fs.h Thu Jul 10 14:40:13 2003
158 @@ -717,6 +717,8 @@ extern unsigned long ext3_count_free_ino
159  extern unsigned long ext3_count_dirs (struct super_block *);
160  extern void ext3_check_inodes_bitmap (struct super_block *);
161  extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
162 +extern struct buffer_head * read_inode_bitmap(struct super_block *, unsigned long);
163 +
164  
165  
166  /* inode.c */
167 @@ -724,7 +726,7 @@ extern int ext3_forget(handle_t *, int, 
168  extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
169  extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
170  
171 -extern int  ext3_get_inode_loc (struct inode *, struct ext3_iloc *);
172 +extern int  ext3_get_inode_loc (struct inode *, struct ext3_iloc *, int);
173  extern void ext3_read_inode (struct inode *);
174  extern void ext3_write_inode (struct inode *, int);
175  extern int  ext3_setattr (struct dentry *, struct iattr *);
176
177 _