⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 journal.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
  }  c_bh = sb_bread(p_s_sb, reiserfs_get_journal_block(p_s_sb) + ((trans_offset + le32_to_cpu(desc->j_len) + 1) % JOURNAL_BLOCK_COUNT)) ;  if (!c_bh) {    brelse(d_bh) ;    return 1 ;  }  commit = (struct reiserfs_journal_commit *)c_bh->b_data ;  if (journal_compare_desc_commit(p_s_sb, desc, commit)) {    reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal_read_transaction, "                   "commit offset %ld had bad time %d or length %d\n", 		   c_bh->b_blocknr - reiserfs_get_journal_block(p_s_sb), 		   le32_to_cpu(commit->j_trans_id), le32_to_cpu(commit->j_len));    brelse(c_bh) ;    brelse(d_bh) ;    return 1;   }  trans_id = le32_to_cpu(desc->j_trans_id) ;  /* now we know we've got a good transaction, and it was inside the valid time ranges */  log_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS) ;  real_blocks = kmalloc(le32_to_cpu(desc->j_len) * sizeof(struct buffer_head *), GFP_NOFS) ;  if (!log_blocks  || !real_blocks) {    brelse(c_bh) ;    brelse(d_bh) ;    kfree(log_blocks) ;    kfree(real_blocks) ;    reiserfs_warning("journal-1169: kmalloc failed, unable to mount FS\n") ;    return -1 ;  }  /* get all the buffer heads */  for(i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {    log_blocks[i] = sb_getblk(p_s_sb, reiserfs_get_journal_block(p_s_sb) + (trans_offset + 1 + i) % JOURNAL_BLOCK_COUNT);    if (i < JOURNAL_TRANS_HALF) {      real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(desc->j_realblock[i])) ;    } else {      real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - JOURNAL_TRANS_HALF])) ;    }    if (real_blocks[i]->b_blocknr >= reiserfs_get_journal_block(p_s_sb) &&        real_blocks[i]->b_blocknr < (reiserfs_get_journal_block(p_s_sb)+JOURNAL_BLOCK_COUNT)) {      reiserfs_warning("journal-1204: REPLAY FAILURE fsck required! Trying to replay onto a log block\n") ;      brelse_array(log_blocks, i) ;      brelse_array(real_blocks, i) ;      brelse(c_bh) ;      brelse(d_bh) ;      kfree(log_blocks) ;      kfree(real_blocks) ;      return -1 ;    }  }  /* read in the log blocks, memcpy to the corresponding real block */  ll_rw_block(READ, le32_to_cpu(desc->j_len), log_blocks) ;  for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {    wait_on_buffer(log_blocks[i]) ;    if (!buffer_uptodate(log_blocks[i])) {      reiserfs_warning("journal-1212: REPLAY FAILURE fsck required! buffer write failed\n") ;      brelse_array(log_blocks + i, le32_to_cpu(desc->j_len) - i) ;      brelse_array(real_blocks, le32_to_cpu(desc->j_len)) ;      brelse(c_bh) ;      brelse(d_bh) ;      kfree(log_blocks) ;      kfree(real_blocks) ;      return -1 ;    }    memcpy(real_blocks[i]->b_data, log_blocks[i]->b_data, real_blocks[i]->b_size) ;    mark_buffer_uptodate(real_blocks[i], 1) ;    brelse(log_blocks[i]) ;  }  /* flush out the real blocks */  for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {    set_bit(BH_Dirty, &(real_blocks[i]->b_state)) ;    ll_rw_block(WRITE, 1, real_blocks + i) ;  }  for (i = 0 ; i < le32_to_cpu(desc->j_len) ; i++) {    wait_on_buffer(real_blocks[i]) ;     if (!buffer_uptodate(real_blocks[i])) {      reiserfs_warning("journal-1226: REPLAY FAILURE, fsck required! buffer write failed\n") ;      brelse_array(real_blocks + i, le32_to_cpu(desc->j_len) - i) ;      brelse(c_bh) ;      brelse(d_bh) ;      kfree(log_blocks) ;      kfree(real_blocks) ;      return -1 ;    }    brelse(real_blocks[i]) ;  }  cur_dblock = reiserfs_get_journal_block(p_s_sb) + ((trans_offset + le32_to_cpu(desc->j_len) + 2) % JOURNAL_BLOCK_COUNT) ;  reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1095: setting journal "                 "start to offset %ld\n", 		 cur_dblock - reiserfs_get_journal_block(p_s_sb)) ;    /* init starting values for the first transaction, in case this is the last transaction to be replayed. */  SB_JOURNAL(p_s_sb)->j_start = cur_dblock - reiserfs_get_journal_block(p_s_sb) ;  SB_JOURNAL(p_s_sb)->j_last_flush_trans_id = trans_id ;  SB_JOURNAL(p_s_sb)->j_trans_id = trans_id + 1;  brelse(c_bh) ;  brelse(d_bh) ;  kfree(log_blocks) ;  kfree(real_blocks) ;  return 0 ;}/*** read and replay the log** on a clean unmount, the journal header's next unflushed pointer will be to an invalid** transaction.  This tests that before finding all the transactions in the log, whic makes normal mount times fast.**** After a crash, this starts with the next unflushed transaction, and replays until it finds one too old, or invalid.**** On exit, it sets things up so the first transaction will work correctly.*/static int journal_read(struct super_block *p_s_sb) {  struct reiserfs_journal_desc *desc ;  unsigned long last_flush_trans_id = 0 ;  unsigned long oldest_trans_id = 0;  unsigned long oldest_invalid_trans_id = 0 ;  time_t start ;  unsigned long last_flush_start = 0;  unsigned long oldest_start = 0;  unsigned long cur_dblock = 0 ;  unsigned long newest_mount_id = 9 ;  struct buffer_head *d_bh ;  struct reiserfs_journal_header *jh ;  int valid_journal_header = 0 ;  int replay_count = 0 ;  int continue_replay = 1 ;  int ret ;  cur_dblock = reiserfs_get_journal_block(p_s_sb) ;  printk("reiserfs: checking transaction log (device %s) ...\n",          kdevname(p_s_sb->s_dev)) ;  start = CURRENT_TIME ;  /* step 1, read in the journal header block.  Check the transaction it says   ** is the first unflushed, and if that transaction is not valid,   ** replay is done  */  SB_JOURNAL(p_s_sb)->j_header_bh = sb_bread(p_s_sb,                                           reiserfs_get_journal_block(p_s_sb) + 					  JOURNAL_BLOCK_COUNT) ;  if (!SB_JOURNAL(p_s_sb)->j_header_bh) {    return 1 ;  }  jh = (struct reiserfs_journal_header *)(SB_JOURNAL(p_s_sb)->j_header_bh->b_data) ;  if (le32_to_cpu(jh->j_first_unflushed_offset) >= 0 &&       le32_to_cpu(jh->j_first_unflushed_offset) < JOURNAL_BLOCK_COUNT &&      le32_to_cpu(jh->j_last_flush_trans_id) > 0) {    last_flush_start = reiserfs_get_journal_block(p_s_sb) +                        le32_to_cpu(jh->j_first_unflushed_offset) ;    last_flush_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) ;    reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1153: found in "                   "header: first_unflushed_offset %d, last_flushed_trans_id "		   "%lu\n", le32_to_cpu(jh->j_first_unflushed_offset), 		   last_flush_trans_id) ;    valid_journal_header = 1 ;    /* now, we try to read the first unflushed offset.  If it is not valid,     ** there is nothing more we can do, and it makes no sense to read     ** through the whole log.    */    d_bh = sb_bread(p_s_sb, reiserfs_get_journal_block(p_s_sb) + le32_to_cpu(jh->j_first_unflushed_offset)) ;    ret = journal_transaction_is_valid(p_s_sb, d_bh, NULL, NULL) ;    if (!ret) {      continue_replay = 0 ;    }    brelse(d_bh) ;  }  if (continue_replay && is_read_only(p_s_sb->s_dev)) {    printk("clm-2076: device is readonly, unable to replay log\n") ;    return -1 ;  }  if (continue_replay && (p_s_sb->s_flags & MS_RDONLY)) {    printk("Warning, log replay starting on readonly filesystem\n") ;      }  /* ok, there are transactions that need to be replayed.  start with the first log block, find  ** all the valid transactions, and pick out the oldest.  */  while(continue_replay && cur_dblock < (reiserfs_get_journal_block(p_s_sb) + JOURNAL_BLOCK_COUNT)) {    d_bh = sb_bread(p_s_sb, cur_dblock) ;    ret = journal_transaction_is_valid(p_s_sb, d_bh, &oldest_invalid_trans_id, &newest_mount_id) ;    if (ret == 1) {      desc = (struct reiserfs_journal_desc *)d_bh->b_data ;      if (oldest_start == 0) { /* init all oldest_ values */        oldest_trans_id = le32_to_cpu(desc->j_trans_id) ;	oldest_start = d_bh->b_blocknr ;	newest_mount_id = le32_to_cpu(desc->j_mount_id) ;	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1179: Setting "	               "oldest_start to offset %lu, trans_id %lu\n", 		       oldest_start - reiserfs_get_journal_block(p_s_sb), 		       oldest_trans_id) ;      } else if (oldest_trans_id > le32_to_cpu(desc->j_trans_id)) {         /* one we just read was older */        oldest_trans_id = le32_to_cpu(desc->j_trans_id) ;	oldest_start = d_bh->b_blocknr ;	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1180: Resetting "	               "oldest_start to offset %lu, trans_id %lu\n", 			oldest_start - reiserfs_get_journal_block(p_s_sb), 			oldest_trans_id) ;      }      if (newest_mount_id < le32_to_cpu(desc->j_mount_id)) {        newest_mount_id = le32_to_cpu(desc->j_mount_id) ;	reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "	              "newest_mount_id to %d\n", le32_to_cpu(desc->j_mount_id));      }      cur_dblock += le32_to_cpu(desc->j_len) + 2 ;    }     else {      cur_dblock++ ;    }    brelse(d_bh) ;  }  /* step three, starting at the oldest transaction, replay */  if (last_flush_start > 0) {    oldest_start = last_flush_start ;    oldest_trans_id = last_flush_trans_id + 1 ;  }   cur_dblock = oldest_start ;  if (oldest_trans_id)  {    reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1206: Starting replay "                   "from offset %lu, trans_id %lu\n", 		   cur_dblock - reiserfs_get_journal_block(p_s_sb), 		   oldest_trans_id) ;  }  replay_count = 0 ;  while(continue_replay && oldest_trans_id > 0) {    ret = journal_read_transaction(p_s_sb, cur_dblock, oldest_start, oldest_trans_id, newest_mount_id) ;    if (ret < 0) {      return ret ;    } else if (ret != 0) {      break ;    }    cur_dblock = reiserfs_get_journal_block(p_s_sb) + SB_JOURNAL(p_s_sb)->j_start ;    replay_count++ ;   if (cur_dblock == oldest_start)        break;  }  if (oldest_trans_id == 0) {    reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1225: No valid "                   "transactions found\n") ;  }  /* j_start does not get set correctly if we don't replay any transactions.  ** if we had a valid journal_header, set j_start to the first unflushed transaction value,  ** copy the trans_id from the header  */  if (valid_journal_header && replay_count == 0) {     SB_JOURNAL(p_s_sb)->j_start = le32_to_cpu(jh->j_first_unflushed_offset) ;    SB_JOURNAL(p_s_sb)->j_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) + 1;    SB_JOURNAL(p_s_sb)->j_last_flush_trans_id = le32_to_cpu(jh->j_last_flush_trans_id) ;    SB_JOURNAL(p_s_sb)->j_mount_id = le32_to_cpu(jh->j_mount_id) + 1;  } else {    SB_JOURNAL(p_s_sb)->j_mount_id = newest_mount_id + 1 ;  }  reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1299: Setting "                 "newest_mount_id to %lu\n", SB_JOURNAL(p_s_sb)->j_mount_id) ;  SB_JOURNAL(p_s_sb)->j_first_unflushed_offset = SB_JOURNAL(p_s_sb)->j_start ;   if (replay_count > 0) {    printk("reiserfs: replayed %d transactions in %lu seconds\n", replay_count, 	    CURRENT_TIME - start) ;  }  if (!is_read_only(p_s_sb->s_dev) &&        _update_journal_header_block(p_s_sb, SB_JOURNAL(p_s_sb)->j_start,                                    SB_JOURNAL(p_s_sb)->j_last_flush_trans_id))  {      /* replay failed, caller must call free_journal_ram and abort      ** the mount      */      return -1 ;  }  return 0 ;}struct reiserfs_journal_commit_task {  struct super_block *p_s_sb ;  int jindex ;  int wake_on_finish ; /* if this is one, we wake the task_done queue, if it                       ** is zero, we free the whole struct on finish		       */  struct reiserfs_journal_commit_task *self ;  struct wait_queue *task_done ;  struct tq_struct task ;} ;static void reiserfs_journal_commit_task_func(struct reiserfs_journal_commit_task *ct) {  struct reiserfs_journal_list *jl ;  jl = SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex ;  flush_commit_list(ct->p_s_sb, SB_JOURNAL_LIST(ct->p_s_sb) + ct->jindex, 1) ;   if (jl->j_len > 0 && atomic_read(&(jl->j_nonzerolen)) > 0 &&       atomic_read(&(jl->j_commit_left)) == 0) {    kupdate_one_transaction(ct->p_s_sb, jl) ;  }  kfree(ct->self) ;}static void setup_commit_task_arg(struct reiserfs_journal_commit_task *ct,                                  struct super_block *p_s_sb, 				  int jindex) {  if (!ct) {    reiserfs_panic(NULL, "journal-1360: setup_commit_task_arg called with NULL struct\n") ;  }  ct->p_s_sb = p_s_sb ;  ct->jindex = jindex ;  ct->task_done = NULL ;  INIT_LIST_HEAD(&ct->task.list) ;  ct->task.sync = 0 ;  ct->task.routine = (void *)(void *)reiserfs_journal_commit_task_func ;   ct->self = ct ;  ct->task.data = (void *)ct ;}static void commit_flush_async(struct super_block *p_s_sb, int jindex) {  struct reiserfs_journal_commit_task *ct ;  /* using GFP_NOFS, GFP_KERNEL could try to flush inodes, which will try  ** to start/join a transaction, which will deadlock  */  ct = kmalloc(sizeof(struct reiserfs_journal_commit_task), GFP_NOFS) ;  if (ct) {    setup_commit_task_arg(ct, p_s_sb, jindex) ;    queue_task(&(ct->task), &reiserfs_commit_thread_tq);    wake_up(&reiserfs_commit_thread_wait) ;  } else {#ifdef CONFIG_REISERFS_CHECK    reiserfs_warning("journal-1540: kmalloc failed, doing sync commit\n") ;#endif    flush_commit_list(p_s_sb, SB_JOURNAL_LIST(p_s_sb) + jindex, 1) ;  }}/*** this is the commit thread.  It is started with kernel_thread on** FS mount, and journal_release() waits for it to exit.**** It could do a periodic commit, but there is a lot code for that** elsewhere right now, and I only wanted to implement this little** piece for starters.**** All we do here is sleep on the j_commit_thread_wait wait queue, and** then run the per filesystem commit task queue when we wakeup.*/static int reiserfs_journal_commit_thread(void *nullp) {  daemonize() ;  spin_lock_irq(&current->sigmask_lock);  sigfillset(&current->blocked);  recalc_sigpending(current);  spin_unlock_irq(&current->sigmask_lock);  sprintf(current->comm, "kreiserfsd") ;  lock_kernel() ;  while(1) {    while(TQ_ACTIVE(reiserfs_commit_thread_tq)) {      run_task_queue(&reiserfs_commit_thread_tq) ;    }    /* if there aren't any more filesystems left, break */    if (reiserfs_mounted_fs_count <= 0) {      run_task_queue(&reiserfs_commit_thread_tq) ;      break ;    }    wake_up(&reiserfs_commit_thread_done) ;    interruptible_sleep_on_timeout(&reiserfs_commit_thread_wait, 5 * HZ) ;  }  unlock_kernel() ;  wake_up(&reiserfs_c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -