recovery.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/recovery.c
  3.  * 
  4.  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  5.  *
  6.  * Copyright 1999-2000 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.  * Journal recovery routines for the generic filesystem journaling code;
  13.  * part of the ext2fs journaling system.  
  14.  */
  15. #ifndef __KERNEL__
  16. #include "jfs_user.h"
  17. #else
  18. #include <linux/sched.h>
  19. #include <linux/fs.h>
  20. #include <linux/jbd.h>
  21. #include <linux/errno.h>
  22. #include <linux/slab.h>
  23. #include <linux/locks.h>
  24. #endif
  25. /*
  26.  * Maintain information about the progress of the recovery job, so that
  27.  * the different passes can carry information between them. 
  28.  */
  29. struct recovery_info 
  30. {
  31. tid_t start_transaction;
  32. tid_t end_transaction;
  33. int nr_replays;
  34. int nr_revokes;
  35. int nr_revoke_hits;
  36. };
  37. enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
  38. static int do_one_pass(journal_t *journal,
  39. struct recovery_info *info, enum passtype pass);
  40. static int scan_revoke_records(journal_t *, struct buffer_head *,
  41. tid_t, struct recovery_info *);
  42. #ifdef __KERNEL__
  43. /* Release readahead buffers after use */
  44. void journal_brelse_array(struct buffer_head *b[], int n)
  45. {
  46. while (--n >= 0)
  47. brelse (b[n]);
  48. }
  49. /*
  50.  * When reading from the journal, we are going through the block device
  51.  * layer directly and so there is no readahead being done for us.  We
  52.  * need to implement any readahead ourselves if we want it to happen at
  53.  * all.  Recovery is basically one long sequential read, so make sure we
  54.  * do the IO in reasonably large chunks.
  55.  *
  56.  * This is not so critical that we need to be enormously clever about
  57.  * the readahead size, though.  128K is a purely arbitrary, good-enough
  58.  * fixed value.
  59.  */
  60. #define MAXBUF 8
  61. static int do_readahead(journal_t *journal, unsigned int start)
  62. {
  63. int err;
  64. unsigned int max, nbufs, next;
  65. unsigned long blocknr;
  66. struct buffer_head *bh;
  67. struct buffer_head * bufs[MAXBUF];
  68. /* Do up to 128K of readahead */
  69. max = start + (128 * 1024 / journal->j_blocksize);
  70. if (max > journal->j_maxlen)
  71. max = journal->j_maxlen;
  72. /* Do the readahead itself.  We'll submit MAXBUF buffer_heads at
  73.  * a time to the block device IO layer. */
  74. nbufs = 0;
  75. for (next = start; next < max; next++) {
  76. err = journal_bmap(journal, next, &blocknr);
  77. if (err) {
  78. printk (KERN_ERR "JBD: bad block at offset %un",
  79. next);
  80. goto failed;
  81. }
  82. bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
  83. if (!bh) {
  84. err = -ENOMEM;
  85. goto failed;
  86. }
  87. if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
  88. bufs[nbufs++] = bh;
  89. if (nbufs == MAXBUF) {
  90. ll_rw_block(READ, nbufs, bufs);
  91. journal_brelse_array(bufs, nbufs);
  92. nbufs = 0;
  93. }
  94. } else
  95. brelse(bh);
  96. }
  97. if (nbufs)
  98. ll_rw_block(READ, nbufs, bufs);
  99. err = 0;
  100. failed:
  101. if (nbufs) 
  102. journal_brelse_array(bufs, nbufs);
  103. return err;
  104. }
  105. #endif /* __KERNEL__ */
  106. /*
  107.  * Read a block from the journal
  108.  */
  109. static int jread(struct buffer_head **bhp, journal_t *journal, 
  110.  unsigned int offset)
  111. {
  112. int err;
  113. unsigned long blocknr;
  114. struct buffer_head *bh;
  115. *bhp = NULL;
  116. J_ASSERT (offset < journal->j_maxlen);
  117. err = journal_bmap(journal, offset, &blocknr);
  118. if (err) {
  119. printk (KERN_ERR "JBD: bad block at offset %un",
  120. offset);
  121. return err;
  122. }
  123. bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
  124. if (!bh)
  125. return -ENOMEM;
  126. if (!buffer_uptodate(bh)) {
  127. /* If this is a brand new buffer, start readahead.
  128.                    Otherwise, we assume we are already reading it.  */
  129. if (!buffer_req(bh))
  130. do_readahead(journal, offset);
  131. wait_on_buffer(bh);
  132. }
  133. if (!buffer_uptodate(bh)) {
  134. printk (KERN_ERR "JBD: Failed to read block at offset %un",
  135. offset);
  136. brelse(bh);
  137. return -EIO;
  138. }
  139. *bhp = bh;
  140. return 0;
  141. }
  142. /*
  143.  * Count the number of in-use tags in a journal descriptor block.
  144.  */
  145. static int count_tags(struct buffer_head *bh, int size)
  146. {
  147. char * tagp;
  148. journal_block_tag_t * tag;
  149. int nr = 0;
  150. tagp = &bh->b_data[sizeof(journal_header_t)];
  151. while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
  152. tag = (journal_block_tag_t *) tagp;
  153. nr++;
  154. tagp += sizeof(journal_block_tag_t);
  155. if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
  156. tagp += 16;
  157. if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
  158. break;
  159. }
  160. return nr;
  161. }
  162. /* Make sure we wrap around the log correctly! */
  163. #define wrap(journal, var)
  164. do {
  165. if (var >= (journal)->j_last)
  166. var -= ((journal)->j_last - (journal)->j_first);
  167. } while (0)
  168. /*
  169.  * journal_recover
  170.  *
  171.  * The primary function for recovering the log contents when mounting a
  172.  * journaled device.  
  173.  * 
  174.  * Recovery is done in three passes.  In the first pass, we look for the
  175.  * end of the log.  In the second, we assemble the list of revoke
  176.  * blocks.  In the third and final pass, we replay any un-revoked blocks
  177.  * in the log.  
  178.  */
  179. int journal_recover(journal_t *journal)
  180. {
  181. int err;
  182. journal_superblock_t * sb;
  183. struct recovery_info info;
  184. memset(&info, 0, sizeof(info));
  185. sb = journal->j_superblock;
  186. /* 
  187.  * The journal superblock's s_start field (the current log head)
  188.  * is always zero if, and only if, the journal was cleanly
  189.  * unmounted.  
  190.  */
  191. if (!sb->s_start) {
  192. jbd_debug(1, "No recovery required, last transaction %dn",
  193.   ntohl(sb->s_sequence));
  194. journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
  195. return 0;
  196. }
  197. err = do_one_pass(journal, &info, PASS_SCAN);
  198. if (!err)
  199. err = do_one_pass(journal, &info, PASS_REVOKE);
  200. if (!err)
  201. err = do_one_pass(journal, &info, PASS_REPLAY);
  202. jbd_debug(0, "JBD: recovery, exit status %d, "
  203.   "recovered transactions %u to %un",
  204.   err, info.start_transaction, info.end_transaction);
  205. jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocksn", 
  206.   info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
  207. /* Restart the log at the next transaction ID, thus invalidating
  208.  * any existing commit records in the log. */
  209. journal->j_transaction_sequence = ++info.end_transaction;
  210. journal_clear_revoke(journal);
  211. fsync_no_super(journal->j_fs_dev);
  212. return err;
  213. }
  214. /*
  215.  * journal_skip_recovery
  216.  *
  217.  * Locate any valid recovery information from the journal and set up the
  218.  * journal structures in memory to ignore it (presumably because the
  219.  * caller has evidence that it is out of date).  
  220.  *
  221.  * We perform one pass over the journal to allow us to tell the user how
  222.  * much recovery information is being erased, and to let us initialise
  223.  * the journal transaction sequence numbers to the next unused ID. 
  224.  */
  225. int journal_skip_recovery(journal_t *journal)
  226. {
  227. int err;
  228. journal_superblock_t * sb;
  229. struct recovery_info info;
  230. memset (&info, 0, sizeof(info));
  231. sb = journal->j_superblock;
  232. err = do_one_pass(journal, &info, PASS_SCAN);
  233. if (err) {
  234. printk(KERN_ERR "JBD: error %d scanning journaln", err);
  235. ++journal->j_transaction_sequence;
  236. } else {
  237. #ifdef CONFIG_JBD_DEBUG
  238. int dropped = info.end_transaction - ntohl(sb->s_sequence);
  239. #endif
  240. jbd_debug(0, 
  241.   "JBD: ignoring %d transaction%s from the journal.n",
  242.   dropped, (dropped == 1) ? "" : "s");
  243. journal->j_transaction_sequence = ++info.end_transaction;
  244. }
  245. journal->j_tail = 0;
  246. return err;
  247. }
  248. static int do_one_pass(journal_t *journal,
  249. struct recovery_info *info, enum passtype pass)
  250. {
  251. unsigned int first_commit_ID, next_commit_ID;
  252. unsigned long next_log_block;
  253. int err, success = 0;
  254. journal_superblock_t * sb;
  255. journal_header_t *  tmp;
  256. struct buffer_head * bh;
  257. unsigned int sequence;
  258. int blocktype;
  259. /* Precompute the maximum metadata descriptors in a descriptor block */
  260. int MAX_BLOCKS_PER_DESC;
  261. MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
  262.        / sizeof(journal_block_tag_t));
  263. /* 
  264.  * First thing is to establish what we expect to find in the log
  265.  * (in terms of transaction IDs), and where (in terms of log
  266.  * block offsets): query the superblock.  
  267.  */
  268. sb = journal->j_superblock;
  269. next_commit_ID = ntohl(sb->s_sequence);
  270. next_log_block = ntohl(sb->s_start);
  271. first_commit_ID = next_commit_ID;
  272. if (pass == PASS_SCAN)
  273. info->start_transaction = first_commit_ID;
  274. jbd_debug(1, "Starting recovery pass %dn", pass);
  275. /*
  276.  * Now we walk through the log, transaction by transaction,
  277.  * making sure that each transaction has a commit block in the
  278.  * expected place.  Each complete transaction gets replayed back
  279.  * into the main filesystem. 
  280.  */
  281. while (1) {
  282. int flags;
  283. char * tagp;
  284. journal_block_tag_t * tag;
  285. struct buffer_head * obh;
  286. struct buffer_head * nbh;
  287. /* If we already know where to stop the log traversal,
  288.  * check right now that we haven't gone past the end of
  289.  * the log. */
  290. if (pass != PASS_SCAN)
  291. if (tid_geq(next_commit_ID, info->end_transaction))
  292. break;
  293. jbd_debug(2, "Scanning for sequence ID %u at %lu/%lun",
  294.   next_commit_ID, next_log_block, journal->j_last);
  295. /* Skip over each chunk of the transaction looking
  296.  * either the next descriptor block or the final commit
  297.  * record. */
  298. jbd_debug(3, "JBD: checking block %ldn", next_log_block);
  299. err = jread(&bh, journal, next_log_block);
  300. if (err)
  301. goto failed;
  302. next_log_block++;
  303. wrap(journal, next_log_block);
  304. /* What kind of buffer is it? 
  305.  * 
  306.  * If it is a descriptor block, check that it has the
  307.  * expected sequence number.  Otherwise, we're all done
  308.  * here. */
  309. tmp = (journal_header_t *)bh->b_data;
  310. if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
  311. brelse(bh);
  312. break;
  313. }
  314. blocktype = ntohl(tmp->h_blocktype);
  315. sequence = ntohl(tmp->h_sequence);
  316. jbd_debug(3, "Found magic %d, sequence %dn", 
  317.   blocktype, sequence);
  318. if (sequence != next_commit_ID) {
  319. brelse(bh);
  320. break;
  321. }
  322. /* OK, we have a valid descriptor block which matches
  323.  * all of the sequence number checks.  What are we going
  324.  * to do with it?  That depends on the pass... */
  325. switch(blocktype) {
  326. case JFS_DESCRIPTOR_BLOCK:
  327. /* If it is a valid descriptor block, replay it
  328.  * in pass REPLAY; otherwise, just skip over the
  329.  * blocks it describes. */
  330. if (pass != PASS_REPLAY) {
  331. next_log_block +=
  332. count_tags(bh, journal->j_blocksize);
  333. wrap(journal, next_log_block);
  334. brelse(bh);
  335. continue;
  336. }
  337. /* A descriptor block: we can now write all of
  338.  * the data blocks.  Yay, useful work is finally
  339.  * getting done here! */
  340. tagp = &bh->b_data[sizeof(journal_header_t)];
  341. while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
  342.        <= journal->j_blocksize) {
  343. unsigned long io_block;
  344. tag = (journal_block_tag_t *) tagp;
  345. flags = ntohl(tag->t_flags);
  346. io_block = next_log_block++;
  347. wrap(journal, next_log_block);
  348. err = jread(&obh, journal, io_block);
  349. if (err) {
  350. /* Recover what we can, but
  351.  * report failure at the end. */
  352. success = err;
  353. printk (KERN_ERR 
  354. "JBD: IO error %d recovering "
  355. "block %ld in logn",
  356. err, io_block);
  357. } else {
  358. unsigned long blocknr;
  359. J_ASSERT(obh != NULL);
  360. blocknr = ntohl(tag->t_blocknr);
  361. /* If the block has been
  362.  * revoked, then we're all done
  363.  * here. */
  364. if (journal_test_revoke
  365.     (journal, blocknr, 
  366.      next_commit_ID)) {
  367. brelse(obh);
  368. ++info->nr_revoke_hits;
  369. goto skip_write;
  370. }
  371. /* Find a buffer for the new
  372.  * data being restored */
  373. nbh = getblk(journal->j_fs_dev, blocknr,
  374.      journal->j_blocksize);
  375. if (nbh == NULL) {
  376. printk(KERN_ERR 
  377.        "JBD: Out of memory "
  378.        "during recovery.n");
  379. err = -ENOMEM;
  380. brelse(bh);
  381. brelse(obh);
  382. goto failed;
  383. }
  384. lock_buffer(nbh);
  385. memcpy(nbh->b_data, obh->b_data,
  386. journal->j_blocksize);
  387. if (flags & JFS_FLAG_ESCAPE) {
  388. *((unsigned int *)bh->b_data) =
  389. htonl(JFS_MAGIC_NUMBER);
  390. }
  391. BUFFER_TRACE(nbh, "marking dirty");
  392. mark_buffer_dirty(nbh);
  393. BUFFER_TRACE(nbh, "marking uptodate");
  394. mark_buffer_uptodate(nbh, 1);
  395. unlock_buffer(nbh);
  396. ++info->nr_replays;
  397. /* ll_rw_block(WRITE, 1, &nbh); */
  398. brelse(obh);
  399. brelse(nbh);
  400. }
  401. skip_write:
  402. tagp += sizeof(journal_block_tag_t);
  403. if (!(flags & JFS_FLAG_SAME_UUID))
  404. tagp += 16;
  405. if (flags & JFS_FLAG_LAST_TAG)
  406. break;
  407. }
  408. brelse(bh);
  409. continue;
  410. case JFS_COMMIT_BLOCK:
  411. /* Found an expected commit block: not much to
  412.  * do other than move on to the next sequence
  413.  * number. */
  414. brelse(bh);
  415. next_commit_ID++;
  416. continue;
  417. case JFS_REVOKE_BLOCK:
  418. /* If we aren't in the REVOKE pass, then we can
  419.  * just skip over this block. */
  420. if (pass != PASS_REVOKE) {
  421. brelse(bh);
  422. continue;
  423. }
  424. err = scan_revoke_records(journal, bh,
  425.   next_commit_ID, info);
  426. brelse(bh);
  427. if (err)
  428. goto failed;
  429. continue;
  430. default:
  431. jbd_debug(3, "Unrecognised magic %d, end of scan.n",
  432.   blocktype);
  433. goto done;
  434. }
  435. }
  436.  done:
  437. /* 
  438.  * We broke out of the log scan loop: either we came to the
  439.  * known end of the log or we found an unexpected block in the
  440.  * log.  If the latter happened, then we know that the "current"
  441.  * transaction marks the end of the valid log.
  442.  */
  443. if (pass == PASS_SCAN)
  444. info->end_transaction = next_commit_ID;
  445. else {
  446. /* It's really bad news if different passes end up at
  447.  * different places (but possible due to IO errors). */
  448. if (info->end_transaction != next_commit_ID) {
  449. printk (KERN_ERR "JBD: recovery pass %d ended at "
  450. "transaction %u, expected %un",
  451. pass, next_commit_ID, info->end_transaction);
  452. if (!success)
  453. success = -EIO;
  454. }
  455. }
  456. return success;
  457.  failed:
  458. return err;
  459. }
  460. /* Scan a revoke record, marking all blocks mentioned as revoked. */
  461. static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, 
  462.        tid_t sequence, struct recovery_info *info)
  463. {
  464. journal_revoke_header_t *header;
  465. int offset, max;
  466. header = (journal_revoke_header_t *) bh->b_data;
  467. offset = sizeof(journal_revoke_header_t);
  468. max = ntohl(header->r_count);
  469. while (offset < max) {
  470. unsigned long blocknr;
  471. int err;
  472. blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
  473. offset += 4;
  474. err = journal_set_revoke(journal, blocknr, sequence);
  475. if (err)
  476. return err;
  477. ++info->nr_revokes;
  478. }
  479. return 0;
  480. }