Whamcloud - gitweb
- set SCSI_MAX_PHYS_SEGMENTS to 256 for 1MB requests
[fs/lustre-release.git] / lustre / kernel_patches / patches / jbd-buffer-release-2.6.10-fc3.patch
1 fix against credits leak in journal_release_buffer()
2
3 The idea is to charge a buffer at a time of modification (journal_dirty_metadata()),
4 not at a time of access (journal_get_*_access()). Each buffer has flag first call
5 journal_dirty_metadata() sets on the buffer.
6
7 Signed-off-by: Alex Tomas <alex@clusterfs.com>
8
9 Index: linux-2.6.10/fs/ext3/ialloc.c
10 ===================================================================
11 --- linux-2.6.10.orig/fs/ext3/ialloc.c  2004-12-25 05:34:45.000000000 +0800
12 +++ linux-2.6.10/fs/ext3/ialloc.c       2005-03-31 18:11:10.672236448 +0800
13 @@ -474,11 +474,9 @@
14                 ino = ext3_find_next_zero_bit((unsigned long *)
15                                 bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
16                 if (ino < EXT3_INODES_PER_GROUP(sb)) {
17 -                       int credits = 0;
18  
19                         BUFFER_TRACE(bitmap_bh, "get_write_access");
20 -                       err = ext3_journal_get_write_access_credits(handle,
21 -                                                       bitmap_bh, &credits);
22 +                       err = ext3_journal_get_write_access(handle, bitmap_bh);
23                         if (err)
24                                 goto fail;
25  
26 @@ -494,7 +492,7 @@
27                                 goto got;
28                         }
29                         /* we lost it */
30 -                       journal_release_buffer(handle, bitmap_bh, credits);
31 +                       journal_release_buffer(handle, bitmap_bh);
32  
33                         if (++ino < EXT3_INODES_PER_GROUP(sb))
34                                 goto repeat_in_this_group;
35 Index: linux-2.6.10/fs/ext3/xattr.c
36 ===================================================================
37 --- linux-2.6.10.orig/fs/ext3/xattr.c   2005-03-31 15:35:26.000000000 +0800
38 +++ linux-2.6.10/fs/ext3/xattr.c        2005-03-31 18:11:10.675235992 +0800
39 @@ -507,8 +507,7 @@
40                         goto skip_get_write_access;
41                 /* ext3_journal_get_write_access() requires an unlocked bh,
42                    which complicates things here. */
43 -               error = ext3_journal_get_write_access_credits(handle, bh,
44 -                                                             &credits);
45 +               error = ext3_journal_get_write_access(handle, bh);
46                 if (error)
47                         goto cleanup;
48                 ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_bdev,
49 @@ -525,7 +524,7 @@
50                         if (ce)
51                                 mb_cache_entry_release(ce);
52                         unlock_buffer(bh);
53 -                       journal_release_buffer(handle, bh, credits);
54 +                       journal_release_buffer(handle, bh);
55                 skip_get_write_access:
56                         ea_bdebug(bh, "cloning");
57                         header = kmalloc(bh->b_size, GFP_KERNEL);
58 @@ -669,8 +668,7 @@
59                                 error = -EDQUOT;
60                                 if (DQUOT_ALLOC_BLOCK(inode, 1)) {
61                                         unlock_buffer(new_bh);
62 -                                       journal_release_buffer(handle, new_bh,
63 -                                                              credits);
64 +                                       journal_release_buffer(handle, new_bh);
65                                         goto cleanup;
66                                 }
67                                 HDR(new_bh)->h_refcount = cpu_to_le32(1 +
68 @@ -986,8 +984,7 @@
69                         ext3_error(inode->i_sb, "ext3_xattr_cache_find",
70                                 "inode %ld: block %ld read error",
71                                 inode->i_ino, (unsigned long) ce->e_block);
72 -               } else if (ext3_journal_get_write_access_credits(
73 -                               handle, bh, credits) == 0) {
74 +               } else if (ext3_journal_get_write_access(handle, bh) == 0) {
75                         /* ext3_journal_get_write_access() requires an unlocked
76                          * bh, which complicates things here. */
77                         lock_buffer(bh);
78 @@ -1003,7 +1000,7 @@
79                                 return bh;
80                         }
81                         unlock_buffer(bh);
82 -                       journal_release_buffer(handle, bh, *credits);
83 +                       journal_release_buffer(handle, bh);
84                         *credits = 0;
85                         brelse(bh);
86                 }
87 Index: linux-2.6.10/fs/ext3/balloc.c
88 ===================================================================
89 --- linux-2.6.10.orig/fs/ext3/balloc.c  2004-12-25 05:33:50.000000000 +0800
90 +++ linux-2.6.10/fs/ext3/balloc.c       2005-03-31 18:14:05.705627328 +0800
91 @@ -342,7 +342,7 @@
92          */
93         /* @@@ check errors */
94         BUFFER_TRACE(bitmap_bh, "getting undo access");
95 -       err = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
96 +       err = ext3_journal_get_undo_access(handle, bitmap_bh);
97         if (err)
98                 goto error_return;
99  
100 @@ -986,7 +986,6 @@
101         unsigned long group_first_block;
102         int ret = 0;
103         int fatal;
104 -       int credits = 0;
105  
106         *errp = 0;
107  
108 @@ -996,7 +995,7 @@
109          * if the buffer is in BJ_Forget state in the committing transaction.
110          */
111         BUFFER_TRACE(bitmap_bh, "get undo access for new block");
112 -       fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
113 +       fatal = ext3_journal_get_undo_access(handle, bitmap_bh);
114         if (fatal) {
115                 *errp = fatal;
116                 return -1;
117 @@ -1087,7 +1086,7 @@
118         }
119  
120         BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
121 -       ext3_journal_release_buffer(handle, bitmap_bh, credits);
122 +       ext3_journal_release_buffer(handle, bitmap_bh);
123         return ret;
124  }
125  
126 Index: linux-2.6.10/fs/jbd/commit.c
127 ===================================================================
128 --- linux-2.6.10.orig/fs/jbd/commit.c   2004-12-25 05:35:27.000000000 +0800
129 +++ linux-2.6.10/fs/jbd/commit.c        2005-03-31 18:11:10.668237056 +0800
130 @@ -204,6 +204,19 @@
131         }
132  
133         /*
134 +        * First, drop modified flag: all accesses to the buffers
135 +        * will be tracked for a new trasaction only -bzzz
136 +        */
137 +       if (commit_transaction->t_buffers) {
138 +               new_jh = jh = commit_transaction->t_buffers->b_tnext;
139 +               do {
140 +                       J_ASSERT_JH(new_jh, new_jh->b_modified == 1);
141 +                       new_jh->b_modified = 0;
142 +                       new_jh = new_jh->b_tnext;
143 +               } while (new_jh != jh);
144 +       }
145 +
146 +       /*
147          * Now try to drop any written-back buffers from the journal's
148          * checkpoint lists.  We do this *before* commit because it potentially
149          * frees some memory
150 Index: linux-2.6.10/fs/jbd/transaction.c
151 ===================================================================
152 --- linux-2.6.10.orig/fs/jbd/transaction.c      2005-03-31 15:35:26.000000000 +0800
153 +++ linux-2.6.10/fs/jbd/transaction.c   2005-03-31 18:11:10.666237360 +0800
154 @@ -522,7 +522,7 @@
155   */
156  static int
157  do_get_write_access(handle_t *handle, struct journal_head *jh,
158 -                       int force_copy, int *credits) 
159 +                       int force_copy) 
160  {
161         struct buffer_head *bh;
162         transaction_t *transaction;
163 @@ -604,11 +604,6 @@
164                 JBUFFER_TRACE(jh, "has frozen data");
165                 J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
166                 jh->b_next_transaction = transaction;
167 -
168 -               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
169 -               handle->h_buffer_credits--;
170 -               if (credits)
171 -                       (*credits)++;
172                 goto done;
173         }
174  
175 @@ -688,10 +683,6 @@
176                 jh->b_next_transaction = transaction;
177         }
178  
179 -       J_ASSERT(handle->h_buffer_credits > 0);
180 -       handle->h_buffer_credits--;
181 -       if (credits)
182 -               (*credits)++;
183  
184         /*
185          * Finally, if the buffer is not journaled right now, we need to make
186 @@ -749,8 +740,7 @@
187   * because we're write()ing a buffer which is also part of a shared mapping.
188   */
189  
190 -int journal_get_write_access(handle_t *handle,
191 -                       struct buffer_head *bh, int *credits)
192 +int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
193  {
194         struct journal_head *jh = journal_add_journal_head(bh);
195         int rc;
196 @@ -758,7 +748,7 @@
197         /* We do not want to get caught playing with fields which the
198          * log thread also manipulates.  Make sure that the buffer
199          * completes any outstanding IO before proceeding. */
200 -       rc = do_get_write_access(handle, jh, 0, credits);
201 +       rc = do_get_write_access(handle, jh, 0);
202         journal_put_journal_head(jh);
203         return rc;
204  }
205 @@ -814,9 +804,6 @@
206         J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
207         J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
208  
209 -       J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
210 -       handle->h_buffer_credits--;
211 -
212         if (jh->b_transaction == NULL) {
213                 jh->b_transaction = transaction;
214                 JBUFFER_TRACE(jh, "file as BJ_Reserved");
215 @@ -869,8 +856,7 @@
216   *
217   * Returns error number or 0 on success.
218   */
219 -int journal_get_undo_access(handle_t *handle, struct buffer_head *bh,
220 -                               int *credits)
221 +int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
222  {
223         int err;
224         struct journal_head *jh = journal_add_journal_head(bh);
225 @@ -883,7 +869,7 @@
226          * make sure that obtaining the committed_data is done
227          * atomically wrt. completion of any outstanding commits.
228          */
229 -       err = do_get_write_access(handle, jh, 1, credits);
230 +       err = do_get_write_access(handle, jh, 1);
231         if (err)
232                 goto out;
233  
234 @@ -1111,6 +1097,17 @@
235  
236         jbd_lock_bh_state(bh);
237  
238 +       if (jh->b_modified == 0) {
239 +               /*
240 +                * This buffer's got modified and becoming part
241 +                * of the transaction. This needs to be done
242 +                * once a transaction -bzzz
243 +                */
244 +               jh->b_modified = 1;
245 +               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
246 +               handle->h_buffer_credits--;
247 +       }
248 +
249         /*
250          * fastpath, to avoid expensive locking.  If this buffer is already
251          * on the running transaction's metadata list there is nothing to do.
252 @@ -1161,24 +1158,11 @@
253   * journal_release_buffer: undo a get_write_access without any buffer
254   * updates, if the update decided in the end that it didn't need access.
255   *
256 - * The caller passes in the number of credits which should be put back for
257 - * this buffer (zero or one).
258 - *
259 - * We leave the buffer attached to t_reserved_list because even though this
260 - * handle doesn't want it, some other concurrent handle may want to journal
261 - * this buffer.  If that handle is curently in between get_write_access() and
262 - * journal_dirty_metadata() then it expects the buffer to be reserved.  If
263 - * we were to rip it off t_reserved_list here, the other handle will explode
264 - * when journal_dirty_metadata is presented with a non-reserved buffer.
265 - *
266 - * If nobody really wants to journal this buffer then it will be thrown
267 - * away at the start of commit.
268   */
269  void
270 -journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
271 +journal_release_buffer(handle_t *handle, struct buffer_head *bh)
272  {
273         BUFFER_TRACE(bh, "entry");
274 -       handle->h_buffer_credits += credits;
275  }
276  
277  /** 
278 @@ -1222,6 +1206,12 @@
279                 goto not_jbd;
280         }
281  
282 +       /*
283 +        * The buffer's going from the transaction, we must drop
284 +        * all references -bzzz
285 +        */
286 +       jh->b_modified = 0;
287 +
288         if (jh->b_transaction == handle->h_transaction) {
289                 J_ASSERT_JH(jh, !jh->b_frozen_data);
290  
291 @@ -2015,7 +2005,10 @@
292         __journal_unfile_buffer(jh);
293         jh->b_transaction = jh->b_next_transaction;
294         jh->b_next_transaction = NULL;
295 -       __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata);
296 +       if (jh->b_modified == 1)
297 +               __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata);
298 +       else
299 +               __journal_file_buffer(jh, jh->b_transaction, BJ_Reserved);
300         J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
301  
302         if (was_dirty)
303 Index: linux-2.6.10/include/linux/journal-head.h
304 ===================================================================
305 --- linux-2.6.10.orig/include/linux/journal-head.h      2004-12-25 05:35:28.000000000 +0800
306 +++ linux-2.6.10/include/linux/journal-head.h   2005-03-31 18:11:10.658238576 +0800
307 @@ -32,6 +32,13 @@
308         unsigned b_jlist;
309  
310         /*
311 +        * This flag signals the buffer has been modified by
312 +        * the currently running transaction
313 +        * [jbd_lock_bh_state()]
314 +        */
315 +       unsigned b_modified;
316 +
317 +       /*
318          * Copy of the buffer data frozen for writing to the log.
319          * [jbd_lock_bh_state()]
320          */
321 Index: linux-2.6.10/include/linux/jbd.h
322 ===================================================================
323 --- linux-2.6.10.orig/include/linux/jbd.h       2005-03-31 15:35:26.000000000 +0800
324 +++ linux-2.6.10/include/linux/jbd.h    2005-03-31 18:12:52.504755552 +0800
325 @@ -867,15 +867,12 @@
326  extern handle_t *journal_start(journal_t *, int nblocks);
327  extern int      journal_restart (handle_t *, int nblocks);
328  extern int      journal_extend (handle_t *, int nblocks);
329 -extern int      journal_get_write_access(handle_t *, struct buffer_head *,
330 -                                               int *credits);
331 +extern int      journal_get_write_access(handle_t *, struct buffer_head *);
332  extern int      journal_get_create_access (handle_t *, struct buffer_head *);
333 -extern int      journal_get_undo_access(handle_t *, struct buffer_head *,
334 -                                               int *credits);
335 +extern int      journal_get_undo_access(handle_t *, struct buffer_head *);
336  extern int      journal_dirty_data (handle_t *, struct buffer_head *);
337  extern int      journal_dirty_metadata (handle_t *, struct buffer_head *);
338 -extern void     journal_release_buffer (handle_t *, struct buffer_head *,
339 -                                               int credits);
340 +extern void     journal_release_buffer (handle_t *, struct buffer_head *);
341  extern int      journal_forget (handle_t *, struct buffer_head *);
342  extern void     journal_sync_buffer (struct buffer_head *);
343  extern int      journal_invalidatepage(journal_t *,
344 Index: linux-2.6.10/include/linux/ext3_jbd.h
345 ===================================================================
346 --- linux-2.6.10.orig/include/linux/ext3_jbd.h  2005-03-31 15:35:26.000000000 +0800
347 +++ linux-2.6.10/include/linux/ext3_jbd.h       2005-03-31 18:11:10.660238272 +0800
348 @@ -113,9 +113,9 @@
349  
350  static inline int
351  __ext3_journal_get_undo_access(const char *where, handle_t *handle,
352 -                               struct buffer_head *bh, int *credits)
353 +                               struct buffer_head *bh)
354  {
355 -       int err = journal_get_undo_access(handle, bh, credits);
356 +       int err = journal_get_undo_access(handle, bh);
357         if (err)
358                 ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
359         return err;
360 @@ -123,19 +123,18 @@
361  
362  static inline int
363  __ext3_journal_get_write_access(const char *where, handle_t *handle,
364 -                               struct buffer_head *bh, int *credits)
365 +                               struct buffer_head *bh)
366  {
367 -       int err = journal_get_write_access(handle, bh, credits);
368 +       int err = journal_get_write_access(handle, bh);
369         if (err)
370                 ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
371         return err;
372  }
373  
374  static inline void
375 -ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh,
376 -                               int credits)
377 +ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
378  {
379 -       journal_release_buffer(handle, bh, credits);
380 +       journal_release_buffer(handle, bh);
381  }
382  
383  static inline int
384 @@ -178,12 +177,10 @@
385  }
386  
387  
388 -#define ext3_journal_get_undo_access(handle, bh, credits) \
389 -       __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh), (credits))
390 +#define ext3_journal_get_undo_access(handle, bh) \
391 +       __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
392  #define ext3_journal_get_write_access(handle, bh) \
393 -       __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), NULL)
394 -#define ext3_journal_get_write_access_credits(handle, bh, credits) \
395 -       __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), (credits))
396 +       __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
397  #define ext3_journal_revoke(handle, blocknr, bh) \
398         __ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
399  #define ext3_journal_get_create_access(handle, bh) \