/* quota ops might need to nest, setup the journal_info pointer for them */ current->journal_info = th ; reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into * the transaction */ current->journal_info = th->t_handle_save ; 
/* quota ops might need to nest, setup the journal_info pointer for them */ current->journal_info = th; reiserfs_discard_all_prealloc(th);	/* it should not involve new blocks into * the transaction */ current->journal_info = th->t_handle_save; 
static int do_journal_end(struct reiserfs_transaction_handle *th, struct super_block  * p_s_sb, unsigned long nblocks, 		          int flags) {  struct reiserfs_journal *journal = SB_JOURNAL (p_s_sb);  struct reiserfs_journal_cnode *cn, *next, *jl_cn;   struct reiserfs_journal_cnode *last_cn = NULL;  struct reiserfs_journal_desc *desc ;   struct reiserfs_journal_commit *commit ;   struct buffer_head *c_bh ; /* commit bh */  struct buffer_head *d_bh ; /* desc bh */  int cur_write_start = 0 ; /* start index of current log write */  int old_start ;  int i ;  int flush = flags & FLUSH_ALL ;  int wait_on_commit = flags & WAIT ;  struct reiserfs_journal_list *jl, *temp_jl;  struct list_head *entry, *safe;  unsigned long jindex;  unsigned long commit_trans_id;  int trans_half;  BUG_ON (th->t_refcount > 1);  BUG_ON (!th->t_trans_id);  put_fs_excl();  current->journal_info = th->t_handle_save;  reiserfs_check_lock_depth(p_s_sb, "journal end");  if (journal->j_len == 0) {      reiserfs_prepare_for_journal(p_s_sb, SB_BUFFER_WITH_SB(p_s_sb), 1) ;      journal_mark_dirty(th, p_s_sb, SB_BUFFER_WITH_SB(p_s_sb)) ;  }  lock_journal(p_s_sb) ;  if (journal->j_next_full_flush) {    flags |= FLUSH_ALL ;    flush = 1 ;  }  if (journal->j_next_async_flush) {    flags |= COMMIT_NOW | WAIT;    wait_on_commit = 1;  }  /* check_journal_end locks the journal, and unlocks if it does not return 1   ** it tells us if we should continue with the journal_end, or just return  */  if (!check_journal_end(th, p_s_sb, nblocks, flags)) {    p_s_sb->s_dirt = 1;    wake_queued_writers(p_s_sb);    reiserfs_async_progress_wait(p_s_sb);    goto out ;  }  /* check_journal_end might set these, check again */  if (journal->j_next_full_flush) {    flush = 1 ;  }  /*  ** j must wait means we have to flush the log blocks, and the real blocks for  ** this transaction  */  if (journal->j_must_wait > 0) {    flush = 1 ;  }#ifdef REISERFS_PREALLOCATE  /* quota ops might need to nest, setup the journal_info pointer for them */  current->journal_info = th ;  reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into				      * the transaction */  current->journal_info = th->t_handle_save ;#endif    /* setup description block */  d_bh = journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + journal->j_start) ;  set_buffer_uptodate(d_bh);  desc = (struct reiserfs_journal_desc *)(d_bh)->b_data ;  memset(d_bh->b_data, 0, d_bh->b_size) ;  memcpy(get_journal_desc_magic (d_bh), JOURNAL_DESC_MAGIC, 8) ;  set_desc_trans_id(desc, journal->j_trans_id) ;  /* setup commit block.  Don't write (keep it clean too) this one until after everyone else is written */  c_bh =  journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + 		 ((journal->j_start + journal->j_len + 1) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;  commit = (struct reiserfs_journal_commit *)c_bh->b_data ;  memset(c_bh->b_data, 0, c_bh->b_size) ;  set_commit_trans_id(commit, journal->j_trans_id) ;  set_buffer_uptodate(c_bh) ;  /* init this journal list */  jl = journal->j_current_jl;  /* we lock the commit before doing anything because   * we want to make sure nobody tries to run flush_commit_list until   * the new transaction is fully setup, and we've already flushed the   * ordered bh list   */  down(&jl->j_commit_lock);  /* save the transaction id in case we need to commit it later */  commit_trans_id = jl->j_trans_id;  atomic_set(&jl->j_older_commits_done, 0) ;  jl->j_trans_id = journal->j_trans_id ;  jl->j_timestamp = journal->j_trans_start_time ;  jl->j_commit_bh = c_bh ;  jl->j_start = journal->j_start ;  jl->j_len = journal->j_len ;  atomic_set(&jl->j_nonzerolen, journal->j_len) ;  atomic_set(&jl->j_commit_left, journal->j_len + 2);  jl->j_realblock = NULL ;  /* The ENTIRE FOR LOOP MUST not cause schedule to occur.  **  for each real block, add it to the journal list hash,  ** copy into real block index array in the commit or desc block  */  trans_half = journal_trans_half(p_s_sb->s_blocksize);  for (i = 0, cn = journal->j_first ; cn ; cn = cn->next, i++) {    if (buffer_journaled (cn->bh)) {      jl_cn = get_cnode(p_s_sb) ;      if (!jl_cn) {        reiserfs_panic(p_s_sb, "journal-1676, get_cnode returned NULL\n") ;      }      if (i == 0) {        jl->j_realblock = jl_cn ;      }      jl_cn->prev = last_cn ;      jl_cn->next = NULL ;      if (last_cn) {        last_cn->next = jl_cn ;      }      last_cn = jl_cn ;      /* make sure the block we are trying to log is not a block          of journal or reserved area */      if (is_block_in_log_or_reserved_area(p_s_sb, cn->bh->b_blocknr)) {        reiserfs_panic(p_s_sb, "journal-2332: Trying to log block %lu, which is a log block\n", cn->bh->b_blocknr) ;      }      jl_cn->blocknr = cn->bh->b_blocknr ;       jl_cn->state = 0 ;      jl_cn->sb = p_s_sb;      jl_cn->bh = cn->bh ;      jl_cn->jlist = jl;      insert_journal_hash(journal->j_list_hash_table, jl_cn) ;      if (i < trans_half) {	desc->j_realblock[i] = cpu_to_le32(cn->bh->b_blocknr) ;      } else {	commit->j_realblock[i - trans_half] = cpu_to_le32(cn->bh->b_blocknr) ;      }    } else {      i-- ;    }  }  set_desc_trans_len(desc, journal->j_len) ;  set_desc_mount_id(desc, journal->j_mount_id) ;  set_desc_trans_id(desc, journal->j_trans_id) ;  set_commit_trans_len(commit, journal->j_len);  /* special check in case all buffers in the journal were marked for not logging */  if (journal->j_len == 0) {    BUG();  }  /* we're about to dirty all the log blocks, mark the description block   * dirty now too.  Don't mark the commit block dirty until all the   * others are on disk   */  mark_buffer_dirty(d_bh);  /* first data block is j_start + 1, so add one to cur_write_start wherever you use it */  cur_write_start = journal->j_start ;  cn = journal->j_first ;  jindex = 1 ; /* start at one so we don't get the desc again */  while(cn) {    clear_buffer_journal_new (cn->bh);    /* copy all the real blocks into log area.  dirty log blocks */    if (buffer_journaled (cn->bh)) {      struct buffer_head *tmp_bh ;      char *addr;      struct page *page;      tmp_bh =  journal_getblk(p_s_sb, SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) + 		       ((cur_write_start + jindex) % SB_ONDISK_JOURNAL_SIZE(p_s_sb))) ;      set_buffer_uptodate(tmp_bh);      page = cn->bh->b_page;      addr = kmap(page);      memcpy(tmp_bh->b_data, addr + offset_in_page(cn->bh->b_data),             cn->bh->b_size);      kunmap(page);      mark_buffer_dirty(tmp_bh);      jindex++ ;      set_buffer_journal_dirty (cn->bh);      clear_buffer_journaled (cn->bh);    } else {      /* JDirty cleared sometime during transaction.  don't log this one */      reiserfs_warning(p_s_sb, "journal-2048: do_journal_end: BAD, buffer in journal hash, but not JDirty!") ;      brelse(cn->bh) ;    }    next = cn->next ;    free_cnode(p_s_sb, cn) ;    cn = next ;    cond_resched();  }  /* we are done  with both the c_bh and d_bh, but  ** c_bh must be written after all other commit blocks,  ** so we dirty/relse c_bh in flush_commit_list, with commit_left <= 1.  */  journal->j_current_jl = alloc_journal_list(p_s_sb);  /* now it is safe to insert this transaction on the main list */  list_add_tail(&jl->j_list, &journal->j_journal_list);  list_add_tail(&jl->j_working_list, &journal->j_working_list);  journal->j_num_work_lists++;  /* reset journal values for the next transaction */  old_start = journal->j_start ;  journal->j_start = (journal->j_start + journal->j_len + 2) % SB_ONDISK_JOURNAL_SIZE(p_s_sb);  atomic_set(&(journal->j_wcount), 0) ;  journal->j_bcount = 0 ;  journal->j_last = NULL ;  journal->j_first = NULL ;  journal->j_len = 0 ;  journal->j_trans_start_time = 0 ;  journal->j_trans_id++ ;  journal->j_current_jl->j_trans_id = journal->j_trans_id;  journal->j_must_wait = 0 ;  journal->j_len_alloc = 0 ;  journal->j_next_full_flush = 0 ;  journal->j_next_async_flush = 0 ;  init_journal_hash(p_s_sb) ;   // make sure reiserfs_add_jh sees the new current_jl before we  // write out the tails  smp_mb();  /* tail conversion targets have to hit the disk before we end the   * transaction.  Otherwise a later transaction might repack the tail   * before this transaction commits, leaving the data block unflushed and   * clean, if we crash before the later transaction commits, the data block   * is lost.   */  if (!list_empty(&jl->j_tail_bh_list)) {      unlock_kernel();      write_ordered_buffers(&journal->j_dirty_buffers_lock,			    journal, jl, &jl->j_tail_bh_list);      lock_kernel();  }  if (!list_empty(&jl->j_tail_bh_list))      BUG();  up(&jl->j_commit_lock);  /* honor the flush wishes from the caller, simple commits can  ** be done outside the journal lock, they are done below  **  ** if we don't flush the commit list right now, we put it into  ** the work queue so the people waiting on the async progress work  ** queue don't wait for this proc to flush journal lists and such.  */  if (flush) {    flush_commit_list(p_s_sb, jl, 1) ;    flush_journal_list(p_s_sb, jl, 1) ;  } else if (!(jl->j_state & LIST_COMMIT_PENDING))    queue_delayed_work(commit_wq, &journal->j_work, HZ/10);  /* if the next transaction has any chance of wrapping, flush   ** transactions that might get overwritten.  If any journal lists are very   ** old flush them as well.    */first_jl:  list_for_each_safe(entry, safe, &journal->j_journal_list) {    temp_jl = JOURNAL_LIST_ENTRY(entry);    if (journal->j_start <= temp_jl->j_start) {      if ((journal->j_start + journal->j_trans_max + 1) >=          temp_jl->j_start)      {	flush_used_journal_lists(p_s_sb, temp_jl);	goto first_jl;      } else if ((journal->j_start +                  journal->j_trans_max + 1) <		  SB_ONDISK_JOURNAL_SIZE(p_s_sb))      {          /* if we don't cross into the next transaction and we don't	   * wrap, there is no way we can overlap any later transactions	   * break now	   */	  break;      }    } else if ((journal->j_start +                journal->j_trans_max + 1) >		SB_ONDISK_JOURNAL_SIZE(p_s_sb))    {      if (((journal->j_start + journal->j_trans_max + 1) %            SB_ONDISK_JOURNAL_SIZE(p_s_sb)) >= temp_jl->j_start)      {	flush_used_journal_lists(p_s_sb, temp_jl);	goto first_jl;      } else {	  /* we don't overlap anything from out start to the end of the	   * log, and our wrapped portion doesn't overlap anything at	   * the start of the log.  We can break	   */	  break;      }    }  }  flush_old_journal_lists(p_s_sb);  journal->j_current_jl->j_list_bitmap = get_list_bitmap(p_s_sb, journal->j_current_jl) ;  if (!(journal->j_current_jl->j_list_bitmap)) {    reiserfs_panic(p_s_sb, "journal-1996: do_journal_end, could not get a list bitmap\n") ;  }  atomic_set(&(journal->j_jlock), 0) ;  unlock_journal(p_s_sb) ;  /* wake up any body waiting to join. */  clear_bit(J_WRITERS_QUEUED, &journal->j_state);  wake_up(&(journal->j_join_wait)) ;  if (!flush && wait_on_commit &&      journal_list_still_alive(p_s_sb, commit_trans_id)) {	  flush_commit_list(p_s_sb, jl, 1) ;  }out:  reiserfs_check_lock_depth(p_s_sb, "journal end2");  memset (th, 0, sizeof (*th));  /* Re-set th->t_super, so we can properly keep track of how many   * persistent transactions there are. We need to do this so if this   * call is part of a failed restart_transaction, we can free it later */  th->t_super = p_s_sb;  return journal->j_errno;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/bd4c625c061c2a38568d0add3478f59172455159/journal.c/buggy/fs/reiserfs/journal.c