~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/jbd/checkpoint.c

Version: ~ [ linux-5.14-rc3 ] ~ [ linux-5.13.5 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.53 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.135 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.198 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.240 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.276 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.276 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/fs/jbd/checkpoint.c
  3  *
  4  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  5  *
  6  * Copyright 1999 Red Hat Software --- All Rights Reserved
  7  *
  8  * This file is part of the Linux kernel and is made available under
  9  * the terms of the GNU General Public License, version 2, or at your
 10  * option, any later version, incorporated herein by reference.
 11  *
 12  * Checkpoint routines for the generic filesystem journaling code.
 13  * Part of the ext2fs journaling system.
 14  *
 15  * Checkpointing is the process of ensuring that a section of the log is
 16  * committed fully to disk, so that that portion of the log can be
 17  * reused.
 18  */
 19 
 20 #include <linux/time.h>
 21 #include <linux/fs.h>
 22 #include <linux/jbd.h>
 23 #include <linux/errno.h>
 24 #include <linux/slab.h>
 25 
 26 /*
 27  * Unlink a buffer from a transaction checkpoint list.
 28  *
 29  * Called with j_list_lock held.
 30  */
 31 static inline void __buffer_unlink_first(struct journal_head *jh)
 32 {
 33         transaction_t *transaction = jh->b_cp_transaction;
 34 
 35         jh->b_cpnext->b_cpprev = jh->b_cpprev;
 36         jh->b_cpprev->b_cpnext = jh->b_cpnext;
 37         if (transaction->t_checkpoint_list == jh) {
 38                 transaction->t_checkpoint_list = jh->b_cpnext;
 39                 if (transaction->t_checkpoint_list == jh)
 40                         transaction->t_checkpoint_list = NULL;
 41         }
 42 }
 43 
 44 /*
 45  * Unlink a buffer from a transaction checkpoint(io) list.
 46  *
 47  * Called with j_list_lock held.
 48  */
 49 static inline void __buffer_unlink(struct journal_head *jh)
 50 {
 51         transaction_t *transaction = jh->b_cp_transaction;
 52 
 53         __buffer_unlink_first(jh);
 54         if (transaction->t_checkpoint_io_list == jh) {
 55                 transaction->t_checkpoint_io_list = jh->b_cpnext;
 56                 if (transaction->t_checkpoint_io_list == jh)
 57                         transaction->t_checkpoint_io_list = NULL;
 58         }
 59 }
 60 
 61 /*
 62  * Move a buffer from the checkpoint list to the checkpoint io list
 63  *
 64  * Called with j_list_lock held
 65  */
 66 static inline void __buffer_relink_io(struct journal_head *jh)
 67 {
 68         transaction_t *transaction = jh->b_cp_transaction;
 69 
 70         __buffer_unlink_first(jh);
 71 
 72         if (!transaction->t_checkpoint_io_list) {
 73                 jh->b_cpnext = jh->b_cpprev = jh;
 74         } else {
 75                 jh->b_cpnext = transaction->t_checkpoint_io_list;
 76                 jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
 77                 jh->b_cpprev->b_cpnext = jh;
 78                 jh->b_cpnext->b_cpprev = jh;
 79         }
 80         transaction->t_checkpoint_io_list = jh;
 81 }
 82 
 83 /*
 84  * Try to release a checkpointed buffer from its transaction.
 85  * Returns 1 if we released it and 2 if we also released the
 86  * whole transaction.
 87  *
 88  * Requires j_list_lock
 89  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
 90  */
 91 static int __try_to_free_cp_buf(struct journal_head *jh)
 92 {
 93         int ret = 0;
 94         struct buffer_head *bh = jh2bh(jh);
 95 
 96         if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
 97             !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
 98                 JBUFFER_TRACE(jh, "remove from checkpoint list");
 99                 ret = __journal_remove_checkpoint(jh) + 1;
100                 jbd_unlock_bh_state(bh);
101                 journal_remove_journal_head(bh);
102                 BUFFER_TRACE(bh, "release");
103                 __brelse(bh);
104         } else {
105                 jbd_unlock_bh_state(bh);
106         }
107         return ret;
108 }
109 
110 /*
111  * __log_wait_for_space: wait until there is space in the journal.
112  *
113  * Called under j-state_lock *only*.  It will be unlocked if we have to wait
114  * for a checkpoint to free up some space in the log.
115  */
116 void __log_wait_for_space(journal_t *journal)
117 {
118         int nblocks, space_left;
119         assert_spin_locked(&journal->j_state_lock);
120 
121         nblocks = jbd_space_needed(journal);
122         while (__log_space_left(journal) < nblocks) {
123                 if (journal->j_flags & JFS_ABORT)
124                         return;
125                 spin_unlock(&journal->j_state_lock);
126                 mutex_lock(&journal->j_checkpoint_mutex);
127 
128                 /*
129                  * Test again, another process may have checkpointed while we
130                  * were waiting for the checkpoint lock. If there are no
131                  * transactions ready to be checkpointed, try to recover
132                  * journal space by calling cleanup_journal_tail(), and if
133                  * that doesn't work, by waiting for the currently committing
134                  * transaction to complete.  If there is absolutely no way
135                  * to make progress, this is either a BUG or corrupted
136                  * filesystem, so abort the journal and leave a stack
137                  * trace for forensic evidence.
138                  */
139                 spin_lock(&journal->j_state_lock);
140                 spin_lock(&journal->j_list_lock);
141                 nblocks = jbd_space_needed(journal);
142                 space_left = __log_space_left(journal);
143                 if (space_left < nblocks) {
144                         int chkpt = journal->j_checkpoint_transactions != NULL;
145                         tid_t tid = 0;
146 
147                         if (journal->j_committing_transaction)
148                                 tid = journal->j_committing_transaction->t_tid;
149                         spin_unlock(&journal->j_list_lock);
150                         spin_unlock(&journal->j_state_lock);
151                         if (chkpt) {
152                                 log_do_checkpoint(journal);
153                         } else if (cleanup_journal_tail(journal) == 0) {
154                                 /* We were able to recover space; yay! */
155                                 ;
156                         } else if (tid) {
157                                 log_wait_commit(journal, tid);
158                         } else {
159                                 printk(KERN_ERR "%s: needed %d blocks and "
160                                        "only had %d space available\n",
161                                        __func__, nblocks, space_left);
162                                 printk(KERN_ERR "%s: no way to get more "
163                                        "journal space\n", __func__);
164                                 WARN_ON(1);
165                                 journal_abort(journal, 0);
166                         }
167                         spin_lock(&journal->j_state_lock);
168                 } else {
169                         spin_unlock(&journal->j_list_lock);
170                 }
171                 mutex_unlock(&journal->j_checkpoint_mutex);
172         }
173 }
174 
175 /*
176  * We were unable to perform jbd_trylock_bh_state() inside j_list_lock.
177  * The caller must restart a list walk.  Wait for someone else to run
178  * jbd_unlock_bh_state().
179  */
180 static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
181         __releases(journal->j_list_lock)
182 {
183         get_bh(bh);
184         spin_unlock(&journal->j_list_lock);
185         jbd_lock_bh_state(bh);
186         jbd_unlock_bh_state(bh);
187         put_bh(bh);
188 }
189 
190 /*
191  * Clean up transaction's list of buffers submitted for io.
192  * We wait for any pending IO to complete and remove any clean
193  * buffers. Note that we take the buffers in the opposite ordering
194  * from the one in which they were submitted for IO.
195  *
196  * Return 0 on success, and return <0 if some buffers have failed
197  * to be written out.
198  *
199  * Called with j_list_lock held.
200  */
201 static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
202 {
203         struct journal_head *jh;
204         struct buffer_head *bh;
205         tid_t this_tid;
206         int released = 0;
207         int ret = 0;
208 
209         this_tid = transaction->t_tid;
210 restart:
211         /* Did somebody clean up the transaction in the meanwhile? */
212         if (journal->j_checkpoint_transactions != transaction ||
213                         transaction->t_tid != this_tid)
214                 return ret;
215         while (!released && transaction->t_checkpoint_io_list) {
216                 jh = transaction->t_checkpoint_io_list;
217                 bh = jh2bh(jh);
218                 if (!jbd_trylock_bh_state(bh)) {
219                         jbd_sync_bh(journal, bh);
220                         spin_lock(&journal->j_list_lock);
221                         goto restart;
222                 }
223                 if (buffer_locked(bh)) {
224                         atomic_inc(&bh->b_count);
225                         spin_unlock(&journal->j_list_lock);
226                         jbd_unlock_bh_state(bh);
227                         wait_on_buffer(bh);
228                         /* the journal_head may have gone by now */
229                         BUFFER_TRACE(bh, "brelse");
230                         __brelse(bh);
231                         spin_lock(&journal->j_list_lock);
232                         goto restart;
233                 }
234                 if (unlikely(buffer_write_io_error(bh)))
235                         ret = -EIO;
236 
237                 /*
238                  * Now in whatever state the buffer currently is, we know that
239                  * it has been written out and so we can drop it from the list
240                  */
241                 released = __journal_remove_checkpoint(jh);
242                 jbd_unlock_bh_state(bh);
243                 journal_remove_journal_head(bh);
244                 __brelse(bh);
245         }
246 
247         return ret;
248 }
249 
250 #define NR_BATCH        64
251 
252 static void
253 __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
254 {
255         int i;
256 
257         ll_rw_block(SWRITE, *batch_count, bhs);
258         for (i = 0; i < *batch_count; i++) {
259                 struct buffer_head *bh = bhs[i];
260                 clear_buffer_jwrite(bh);
261                 BUFFER_TRACE(bh, "brelse");
262                 __brelse(bh);
263         }
264         *batch_count = 0;
265 }
266 
267 /*
268  * Try to flush one buffer from the checkpoint list to disk.
269  *
270  * Return 1 if something happened which requires us to abort the current
271  * scan of the checkpoint list.  Return <0 if the buffer has failed to
272  * be written out.
273  *
274  * Called with j_list_lock held and drops it if 1 is returned
275  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
276  */
277 static int __process_buffer(journal_t *journal, struct journal_head *jh,
278                         struct buffer_head **bhs, int *batch_count)
279 {
280         struct buffer_head *bh = jh2bh(jh);
281         int ret = 0;
282 
283         if (buffer_locked(bh)) {
284                 atomic_inc(&bh->b_count);
285                 spin_unlock(&journal->j_list_lock);
286                 jbd_unlock_bh_state(bh);
287                 wait_on_buffer(bh);
288                 /* the journal_head may have gone by now */
289                 BUFFER_TRACE(bh, "brelse");
290                 __brelse(bh);
291                 ret = 1;
292         } else if (jh->b_transaction != NULL) {
293                 transaction_t *t = jh->b_transaction;
294                 tid_t tid = t->t_tid;
295 
296                 spin_unlock(&journal->j_list_lock);
297                 jbd_unlock_bh_state(bh);
298                 log_start_commit(journal, tid);
299                 log_wait_commit(journal, tid);
300                 ret = 1;
301         } else if (!buffer_dirty(bh)) {
302                 ret = 1;
303                 if (unlikely(buffer_write_io_error(bh)))
304                         ret = -EIO;
305                 J_ASSERT_JH(jh, !buffer_jbddirty(bh));
306                 BUFFER_TRACE(bh, "remove from checkpoint");
307                 __journal_remove_checkpoint(jh);
308                 spin_unlock(&journal->j_list_lock);
309                 jbd_unlock_bh_state(bh);
310                 journal_remove_journal_head(bh);
311                 __brelse(bh);
312         } else {
313                 /*
314                  * Important: we are about to write the buffer, and
315                  * possibly block, while still holding the journal lock.
316                  * We cannot afford to let the transaction logic start
317                  * messing around with this buffer before we write it to
318                  * disk, as that would break recoverability.
319                  */
320                 BUFFER_TRACE(bh, "queue");
321                 get_bh(bh);
322                 J_ASSERT_BH(bh, !buffer_jwrite(bh));
323                 set_buffer_jwrite(bh);
324                 bhs[*batch_count] = bh;
325                 __buffer_relink_io(jh);
326                 jbd_unlock_bh_state(bh);
327                 (*batch_count)++;
328                 if (*batch_count == NR_BATCH) {
329                         spin_unlock(&journal->j_list_lock);
330                         __flush_batch(journal, bhs, batch_count);
331                         ret = 1;
332                 }
333         }
334         return ret;
335 }
336 
337 /*
338  * Perform an actual checkpoint. We take the first transaction on the
339  * list of transactions to be checkpointed and send all its buffers
340  * to disk. We submit larger chunks of data at once.
341  *
342  * The journal should be locked before calling this function.
343  * Called with j_checkpoint_mutex held.
344  */
345 int log_do_checkpoint(journal_t *journal)
346 {
347         transaction_t *transaction;
348         tid_t this_tid;
349         int result;
350 
351         jbd_debug(1, "Start checkpoint\n");
352 
353         /*
354          * First thing: if there are any transactions in the log which
355          * don't need checkpointing, just eliminate them from the
356          * journal straight away.
357          */
358         result = cleanup_journal_tail(journal);
359         jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
360         if (result <= 0)
361                 return result;
362 
363         /*
364          * OK, we need to start writing disk blocks.  Take one transaction
365          * and write it.
366          */
367         result = 0;
368         spin_lock(&journal->j_list_lock);
369         if (!journal->j_checkpoint_transactions)
370                 goto out;
371         transaction = journal->j_checkpoint_transactions;
372         this_tid = transaction->t_tid;
373 restart:
374         /*
375          * If someone cleaned up this transaction while we slept, we're
376          * done (maybe it's a new transaction, but it fell at the same
377          * address).
378          */
379         if (journal->j_checkpoint_transactions == transaction &&
380                         transaction->t_tid == this_tid) {
381                 int batch_count = 0;
382                 struct buffer_head *bhs[NR_BATCH];
383                 struct journal_head *jh;
384                 int retry = 0, err;
385 
386                 while (!retry && transaction->t_checkpoint_list) {
387                         struct buffer_head *bh;
388 
389                         jh = transaction->t_checkpoint_list;
390                         bh = jh2bh(jh);
391                         if (!jbd_trylock_bh_state(bh)) {
392                                 jbd_sync_bh(journal, bh);
393                                 retry = 1;
394                                 break;
395                         }
396                         retry = __process_buffer(journal, jh, bhs,&batch_count);
397                         if (retry < 0 && !result)
398                                 result = retry;
399                         if (!retry && (need_resched() ||
400                                 spin_needbreak(&journal->j_list_lock))) {
401                                 spin_unlock(&journal->j_list_lock);
402                                 retry = 1;
403                                 break;
404                         }
405                 }
406 
407                 if (batch_count) {
408                         if (!retry) {
409                                 spin_unlock(&journal->j_list_lock);
410                                 retry = 1;
411                         }
412                         __flush_batch(journal, bhs, &batch_count);
413                 }
414 
415                 if (retry) {
416                         spin_lock(&journal->j_list_lock);
417                         goto restart;
418                 }
419                 /*
420                  * Now we have cleaned up the first transaction's checkpoint
421                  * list. Let's clean up the second one
422                  */
423                 err = __wait_cp_io(journal, transaction);
424                 if (!result)
425                         result = err;
426         }
427 out:
428         spin_unlock(&journal->j_list_lock);
429         if (result < 0)
430                 journal_abort(journal, result);
431         else
432                 result = cleanup_journal_tail(journal);
433 
434         return (result < 0) ? result : 0;
435 }
436 
437 /*
438  * Check the list of checkpoint transactions for the journal to see if
439  * we have already got rid of any since the last update of the log tail
440  * in the journal superblock.  If so, we can instantly roll the
441  * superblock forward to remove those transactions from the log.
442  *
443  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
444  *
445  * Called with the journal lock held.
446  *
447  * This is the only part of the journaling code which really needs to be
448  * aware of transaction aborts.  Checkpointing involves writing to the
449  * main filesystem area rather than to the journal, so it can proceed
450  * even in abort state, but we must not update the super block if
451  * checkpointing may have failed.  Otherwise, we would lose some metadata
452  * buffers which should be written-back to the filesystem.
453  */
454 
455 int cleanup_journal_tail(journal_t *journal)
456 {
457         transaction_t * transaction;
458         tid_t           first_tid;
459         unsigned int    blocknr, freed;
460 
461         if (is_journal_aborted(journal))
462                 return 1;
463 
464         /* OK, work out the oldest transaction remaining in the log, and
465          * the log block it starts at.
466          *
467          * If the log is now empty, we need to work out which is the
468          * next transaction ID we will write, and where it will
469          * start. */
470 
471         spin_lock(&journal->j_state_lock);
472         spin_lock(&journal->j_list_lock);
473         transaction = journal->j_checkpoint_transactions;
474         if (transaction) {
475                 first_tid = transaction->t_tid;
476                 blocknr = transaction->t_log_start;
477         } else if ((transaction = journal->j_committing_transaction) != NULL) {
478                 first_tid = transaction->t_tid;
479                 blocknr = transaction->t_log_start;
480         } else if ((transaction = journal->j_running_transaction) != NULL) {
481                 first_tid = transaction->t_tid;
482                 blocknr = journal->j_head;
483         } else {
484                 first_tid = journal->j_transaction_sequence;
485                 blocknr = journal->j_head;
486         }
487         spin_unlock(&journal->j_list_lock);
488         J_ASSERT(blocknr != 0);
489 
490         /* If the oldest pinned transaction is at the tail of the log
491            already then there's not much we can do right now. */
492         if (journal->j_tail_sequence == first_tid) {
493                 spin_unlock(&journal->j_state_lock);
494                 return 1;
495         }
496 
497         /* OK, update the superblock to recover the freed space.
498          * Physical blocks come first: have we wrapped beyond the end of
499          * the log?  */
500         freed = blocknr - journal->j_tail;
501         if (blocknr < journal->j_tail)
502                 freed = freed + journal->j_last - journal->j_first;
503 
504         jbd_debug(1,
505                   "Cleaning journal tail from %d to %d (offset %u), "
506                   "freeing %u\n",
507                   journal->j_tail_sequence, first_tid, blocknr, freed);
508 
509         journal->j_free += freed;
510         journal->j_tail_sequence = first_tid;
511         journal->j_tail = blocknr;
512         spin_unlock(&journal->j_state_lock);
513         if (!(journal->j_flags & JFS_ABORT))
514                 journal_update_superblock(journal, 1);
515         return 0;
516 }
517 
518 
519 /* Checkpoint list management */
520 
521 /*
522  * journal_clean_one_cp_list
523  *
524  * Find all the written-back checkpoint buffers in the given list and release them.
525  *
526  * Called with the journal locked.
527  * Called with j_list_lock held.
528  * Returns number of bufers reaped (for debug)
529  */
530 
531 static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
532 {
533         struct journal_head *last_jh;
534         struct journal_head *next_jh = jh;
535         int ret, freed = 0;
536 
537         *released = 0;
538         if (!jh)
539                 return 0;
540 
541         last_jh = jh->b_cpprev;
542         do {
543                 jh = next_jh;
544                 next_jh = jh->b_cpnext;
545                 /* Use trylock because of the ranking */
546                 if (jbd_trylock_bh_state(jh2bh(jh))) {
547                         ret = __try_to_free_cp_buf(jh);
548                         if (ret) {
549                                 freed++;
550                                 if (ret == 2) {
551                                         *released = 1;
552                                         return freed;
553                                 }
554                         }
555                 }
556                 /*
557                  * This function only frees up some memory
558                  * if possible so we dont have an obligation
559                  * to finish processing. Bail out if preemption
560                  * requested:
561                  */
562                 if (need_resched())
563                         return freed;
564         } while (jh != last_jh);
565 
566         return freed;
567 }
568 
569 /*
570  * journal_clean_checkpoint_list
571  *
572  * Find all the written-back checkpoint buffers in the journal and release them.
573  *
574  * Called with the journal locked.
575  * Called with j_list_lock held.
576  * Returns number of buffers reaped (for debug)
577  */
578 
579 int __journal_clean_checkpoint_list(journal_t *journal)
580 {
581         transaction_t *transaction, *last_transaction, *next_transaction;
582         int ret = 0;
583         int released;
584 
585         transaction = journal->j_checkpoint_transactions;
586         if (!transaction)
587                 goto out;
588 
589         last_transaction = transaction->t_cpprev;
590         next_transaction = transaction;
591         do {
592                 transaction = next_transaction;
593                 next_transaction = transaction->t_cpnext;
594                 ret += journal_clean_one_cp_list(transaction->
595                                 t_checkpoint_list, &released);
596                 /*
597                  * This function only frees up some memory if possible so we
598                  * dont have an obligation to finish processing. Bail out if
599                  * preemption requested:
600                  */
601                 if (need_resched())
602                         goto out;
603                 if (released)
604                         continue;
605                 /*
606                  * It is essential that we are as careful as in the case of
607                  * t_checkpoint_list with removing the buffer from the list as
608                  * we can possibly see not yet submitted buffers on io_list
609                  */
610                 ret += journal_clean_one_cp_list(transaction->
611                                 t_checkpoint_io_list, &released);
612                 if (need_resched())
613                         goto out;
614         } while (transaction != last_transaction);
615 out:
616         return ret;
617 }
618 
619 /*
620  * journal_remove_checkpoint: called after a buffer has been committed
621  * to disk (either by being write-back flushed to disk, or being
622  * committed to the log).
623  *
624  * We cannot safely clean a transaction out of the log until all of the
625  * buffer updates committed in that transaction have safely been stored
626  * elsewhere on disk.  To achieve this, all of the buffers in a
627  * transaction need to be maintained on the transaction's checkpoint
628  * lists until they have been rewritten, at which point this function is
629  * called to remove the buffer from the existing transaction's
630  * checkpoint lists.
631  *
632  * The function returns 1 if it frees the transaction, 0 otherwise.
633  *
634  * This function is called with the journal locked.
635  * This function is called with j_list_lock held.
636  * This function is called with jbd_lock_bh_state(jh2bh(jh))
637  */
638 
639 int __journal_remove_checkpoint(struct journal_head *jh)
640 {
641         transaction_t *transaction;
642         journal_t *journal;
643         int ret = 0;
644 
645         JBUFFER_TRACE(jh, "entry");
646 
647         if ((transaction = jh->b_cp_transaction) == NULL) {
648                 JBUFFER_TRACE(jh, "not on transaction");
649                 goto out;
650         }
651         journal = transaction->t_journal;
652 
653         __buffer_unlink(jh);
654         jh->b_cp_transaction = NULL;
655 
656         if (transaction->t_checkpoint_list != NULL ||
657             transaction->t_checkpoint_io_list != NULL)
658                 goto out;
659         JBUFFER_TRACE(jh, "transaction has no more buffers");
660 
661         /*
662          * There is one special case to worry about: if we have just pulled the
663          * buffer off a running or committing transaction's checkpoing list,
664          * then even if the checkpoint list is empty, the transaction obviously
665          * cannot be dropped!
666          *
667          * The locking here around t_state is a bit sleazy.
668          * See the comment at the end of journal_commit_transaction().
669          */
670         if (transaction->t_state != T_FINISHED) {
671                 JBUFFER_TRACE(jh, "belongs to running/committing transaction");
672                 goto out;
673         }
674 
675         /* OK, that was the last buffer for the transaction: we can now
676            safely remove this transaction from the log */
677 
678         __journal_drop_transaction(journal, transaction);
679 
680         /* Just in case anybody was waiting for more transactions to be
681            checkpointed... */
682         wake_up(&journal->j_wait_logspace);
683         ret = 1;
684 out:
685         JBUFFER_TRACE(jh, "exit");
686         return ret;
687 }
688 
689 /*
690  * journal_insert_checkpoint: put a committed buffer onto a checkpoint
691  * list so that we know when it is safe to clean the transaction out of
692  * the log.
693  *
694  * Called with the journal locked.
695  * Called with j_list_lock held.
696  */
697 void __journal_insert_checkpoint(struct journal_head *jh,
698                                transaction_t *transaction)
699 {
700         JBUFFER_TRACE(jh, "entry");
701         J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
702         J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
703 
704         jh->b_cp_transaction = transaction;
705 
706         if (!transaction->t_checkpoint_list) {
707                 jh->b_cpnext = jh->b_cpprev = jh;
708         } else {
709                 jh->b_cpnext = transaction->t_checkpoint_list;
710                 jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
711                 jh->b_cpprev->b_cpnext = jh;
712                 jh->b_cpnext->b_cpprev = jh;
713         }
714         transaction->t_checkpoint_list = jh;
715 }
716 
717 /*
718  * We've finished with this transaction structure: adios...
719  *
720  * The transaction must have no links except for the checkpoint by this
721  * point.
722  *
723  * Called with the journal locked.
724  * Called with j_list_lock held.
725  */
726 
727 void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
728 {
729         assert_spin_locked(&journal->j_list_lock);
730         if (transaction->t_cpnext) {
731                 transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
732                 transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
733                 if (journal->j_checkpoint_transactions == transaction)
734                         journal->j_checkpoint_transactions =
735                                 transaction->t_cpnext;
736                 if (journal->j_checkpoint_transactions == transaction)
737                         journal->j_checkpoint_transactions = NULL;
738         }
739 
740         J_ASSERT(transaction->t_state == T_FINISHED);
741         J_ASSERT(transaction->t_buffers == NULL);
742         J_ASSERT(transaction->t_sync_datalist == NULL);
743         J_ASSERT(transaction->t_forget == NULL);
744         J_ASSERT(transaction->t_iobuf_list == NULL);
745         J_ASSERT(transaction->t_shadow_list == NULL);
746         J_ASSERT(transaction->t_log_list == NULL);
747         J_ASSERT(transaction->t_checkpoint_list == NULL);
748         J_ASSERT(transaction->t_checkpoint_io_list == NULL);
749         J_ASSERT(transaction->t_updates == 0);
750         J_ASSERT(journal->j_committing_transaction != transaction);
751         J_ASSERT(journal->j_running_transaction != transaction);
752 
753         jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
754         kfree(transaction);
755 }
756 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp