tail_conversion.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright 1999-2002 Hans Reiser, see reiserfs/README for licensing and copyright details
  3.  */
  4. #include <linux/config.h>
  5. #include <linux/sched.h>
  6. #include <linux/pagemap.h>
  7. #include <linux/reiserfs_fs.h>
  8. #include <linux/locks.h>
  9. /* access to tail : when one is going to read tail it must make sure, that is not running.
  10.  direct2indirect and indirect2direct can not run concurrently */
  11. /* Converts direct items to an unformatted node. Panics if file has no
  12.    tail. -ENOSPC if no disk space for conversion */
  13. /* path points to first direct item of the file regarless of how many of
  14.    them are there */
  15. int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inode, 
  16.      struct path * path, struct buffer_head * unbh,
  17.      loff_t tail_offset)
  18. {
  19.     struct super_block * sb = inode->i_sb;
  20.     struct buffer_head *up_to_date_bh ;
  21.     struct item_head * p_le_ih = PATH_PITEM_HEAD (path);
  22.     unsigned long total_tail = 0 ;
  23.     struct cpu_key end_key;  /* Key to search for the last byte of the
  24. converted item. */
  25.     struct item_head ind_ih; /* new indirect item to be inserted or
  26.                                 key of unfm pointer to be pasted */
  27.     int n_blk_size,
  28.       n_retval;   /* returned value for reiserfs_insert_item and clones */
  29.     struct unfm_nodeinfo unfm_ptr;  /* Handle on an unformatted node
  30.        that will be inserted in the
  31.        tree. */
  32.     sb->u.reiserfs_sb.s_direct2indirect ++;
  33.     n_blk_size = sb->s_blocksize;
  34.     /* and key to search for append or insert pointer to the new
  35.        unformatted node. */
  36.     copy_item_head (&ind_ih, p_le_ih);
  37.     set_le_ih_k_offset (&ind_ih, tail_offset);
  38.     set_le_ih_k_type (&ind_ih, TYPE_INDIRECT);
  39.     /* Set the key to search for the place for new unfm pointer */
  40.     make_cpu_key (&end_key, inode, tail_offset, TYPE_INDIRECT, 4);
  41.     // FIXME: we could avoid this 
  42.     if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) {
  43. reiserfs_warning ("PAP-14030: direct2indirect: "
  44. "pasted or inserted byte exists in the tree %K. "
  45. "Use fsck to repair.n", &end_key);
  46. pathrelse(path);
  47. return -EIO;
  48.     }
  49.     
  50.     p_le_ih = PATH_PITEM_HEAD (path);
  51.     unfm_ptr.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr);
  52.     unfm_ptr.unfm_freespace = 0; // ???
  53.     
  54.     if ( is_statdata_le_ih (p_le_ih) )  {
  55. /* Insert new indirect item. */
  56. set_ih_free_space (&ind_ih, 0); /* delete at nearest future */
  57.         put_ih_item_len( &ind_ih, UNFM_P_SIZE );
  58. PATH_LAST_POSITION (path)++;
  59. n_retval = reiserfs_insert_item (th, path, &end_key, &ind_ih, 
  60.  (char *)&unfm_ptr);
  61.     } else {
  62. /* Paste into last indirect item of an object. */
  63. n_retval = reiserfs_paste_into_item(th, path, &end_key,
  64.     (char *)&unfm_ptr, UNFM_P_SIZE);
  65.     }
  66.     if ( n_retval ) {
  67. return n_retval;
  68.     }
  69.     // note: from here there are two keys which have matching first
  70.     // three key components. They only differ by the fourth one.
  71.     /* Set the key to search for the direct items of the file */
  72.     make_cpu_key (&end_key, inode, max_reiserfs_offset (inode), TYPE_DIRECT, 4);
  73.     /* Move bytes from the direct items to the new unformatted node
  74.        and delete them. */
  75.     while (1)  {
  76. int tail_size;
  77. /* end_key.k_offset is set so, that we will always have found
  78.            last item of the file */
  79. if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND )
  80.     reiserfs_panic (sb, "PAP-14050: direct2indirect: "
  81.     "direct item (%K) not found", &end_key);
  82. p_le_ih = PATH_PITEM_HEAD (path);
  83. RFALSE( !is_direct_le_ih (p_le_ih),
  84.         "vs-14055: direct item expected(%K), found %h",
  85.                 &end_key, p_le_ih);
  86.         tail_size = (le_ih_k_offset (p_le_ih) & (n_blk_size - 1))
  87.             + ih_item_len(p_le_ih) - 1;
  88. /* we only send the unbh pointer if the buffer is not up to date.
  89. ** this avoids overwriting good data from writepage() with old data
  90. ** from the disk or buffer cache
  91. */
  92. if (buffer_uptodate(unbh) || Page_Uptodate(unbh->b_page)) {
  93.     up_to_date_bh = NULL ;
  94. } else {
  95.     up_to_date_bh = unbh ;
  96. }
  97. n_retval = reiserfs_delete_item (th, path, &end_key, inode, 
  98.                                  up_to_date_bh) ;
  99. total_tail += n_retval ;
  100. if (tail_size == n_retval)
  101.     // done: file does not have direct items anymore
  102.     break;
  103.     }
  104.     /* if we've copied bytes from disk into the page, we need to zero
  105.     ** out the unused part of the block (it was not up to date before)
  106.     ** the page is still kmapped (by whoever called reiserfs_get_block)
  107.     */
  108.     if (up_to_date_bh) {
  109.         unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1);
  110. memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ;
  111.     }
  112.     inode->u.reiserfs_i.i_first_direct_byte = U32_MAX;
  113.     return 0;
  114. }
  115. /* stolen from fs/buffer.c */
  116. void reiserfs_unmap_buffer(struct buffer_head *bh) {
  117.   if (buffer_mapped(bh)) {
  118.     if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
  119.       BUG() ;
  120.     }
  121.     mark_buffer_clean(bh) ;
  122.     lock_buffer(bh) ;
  123.     clear_bit(BH_Mapped, &bh->b_state) ;
  124.     clear_bit(BH_Req, &bh->b_state) ;
  125.     clear_bit(BH_New, &bh->b_state) ;
  126.     unlock_buffer(bh) ;
  127.   }
  128. }
  129. static void
  130. unmap_buffers(struct page *page, loff_t pos) {
  131.   struct buffer_head *bh ;
  132.   struct buffer_head *head ;
  133.   struct buffer_head *next ;
  134.   unsigned long tail_index ;
  135.   unsigned long cur_index ;
  136.   if (page) {
  137.     if (page->buffers) {
  138.       tail_index = pos & (PAGE_CACHE_SIZE - 1) ;
  139.       cur_index = 0 ;
  140.       head = page->buffers ;
  141.       bh = head ;
  142.       do {
  143. next = bh->b_this_page ;
  144.         /* we want to unmap the buffers that contain the tail, and
  145.         ** all the buffers after it (since the tail must be at the
  146.         ** end of the file).  We don't want to unmap file data 
  147.         ** before the tail, since it might be dirty and waiting to 
  148.         ** reach disk
  149.         */
  150.         cur_index += bh->b_size ;
  151.         if (cur_index > tail_index) {
  152.           reiserfs_unmap_buffer(bh) ;
  153.         }
  154. bh = next ;
  155.       } while (bh != head) ;
  156.     }
  157.   } 
  158. }
  159. /* this first locks inode (neither reads nor sync are permitted),
  160.    reads tail through page cache, insert direct item. When direct item
  161.    inserted successfully inode is left locked. Return value is always
  162.    what we expect from it (number of cut bytes). But when tail remains
  163.    in the unformatted node, we set mode to SKIP_BALANCING and unlock
  164.    inode */
  165. int indirect2direct (struct reiserfs_transaction_handle *th, 
  166.      struct inode * p_s_inode,
  167.      struct page *page, 
  168.      struct path * p_s_path, /* path to the indirect item. */
  169.      const struct cpu_key * p_s_item_key, /* Key to look for unformatted node pointer to be cut. */
  170.      loff_t n_new_file_size, /* New file size. */
  171.      char * p_c_mode)
  172. {
  173.     struct super_block * p_s_sb = p_s_inode->i_sb;
  174.     struct item_head      s_ih;
  175.     unsigned long n_block_size = p_s_sb->s_blocksize;
  176.     char * tail;
  177.     int tail_len, round_tail_len;
  178.     loff_t pos, pos1; /* position of first byte of the tail */
  179.     struct cpu_key key;
  180.     p_s_sb->u.reiserfs_sb.s_indirect2direct ++;
  181.     *p_c_mode = M_SKIP_BALANCING;
  182.     /* store item head path points to. */
  183.     copy_item_head (&s_ih, PATH_PITEM_HEAD(p_s_path));
  184.     tail_len = (n_new_file_size & (n_block_size - 1));
  185.     if (get_inode_sd_version (p_s_inode) == STAT_DATA_V2)
  186. round_tail_len = ROUND_UP (tail_len);
  187.     else
  188. round_tail_len = tail_len;
  189.     pos = le_ih_k_offset (&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize;
  190.     pos1 = pos;
  191.     // we are protected by i_sem. The tail can not disapper, not
  192.     // append can be done either
  193.     // we are in truncate or packing tail in file_release
  194.     tail = (char *)kmap(page) ; /* this can schedule */
  195.     if (path_changed (&s_ih, p_s_path)) {
  196. /* re-search indirect item */
  197. if ( search_for_position_by_key (p_s_sb, p_s_item_key, p_s_path) == POSITION_NOT_FOUND )
  198.     reiserfs_panic(p_s_sb, "PAP-5520: indirect2direct: "
  199.    "item to be converted %K does not exist", p_s_item_key);
  200. copy_item_head(&s_ih, PATH_PITEM_HEAD(p_s_path));
  201. #ifdef CONFIG_REISERFS_CHECK
  202. pos = le_ih_k_offset (&s_ih) - 1 + 
  203.     (ih_item_len(&s_ih) / UNFM_P_SIZE - 1) * p_s_sb->s_blocksize;
  204. if (pos != pos1)
  205.     reiserfs_panic (p_s_sb, "vs-5530: indirect2direct: "
  206.     "tail position changed while we were reading it");
  207. #endif
  208.     }
  209.     /* Set direct item header to insert. */
  210.     make_le_item_head (&s_ih, 0, get_inode_item_key_version (p_s_inode), pos1 + 1,
  211.        TYPE_DIRECT, round_tail_len, 0xffff/*ih_free_space*/);
  212.     /* we want a pointer to the first byte of the tail in the page.
  213.     ** the page was locked and this part of the page was up to date when
  214.     ** indirect2direct was called, so we know the bytes are still valid
  215.     */
  216.     tail = tail + (pos & (PAGE_CACHE_SIZE - 1)) ;
  217.     PATH_LAST_POSITION(p_s_path)++;
  218.     key = *p_s_item_key;
  219.     set_cpu_key_k_type (&key, TYPE_DIRECT);
  220.     key.key_length = 4;
  221.     /* Insert tail as new direct item in the tree */
  222.     if ( reiserfs_insert_item(th, p_s_path, &key, &s_ih,
  223.       tail ? tail : NULL) < 0 ) {
  224. /* No disk memory. So we can not convert last unformatted node
  225.    to the direct item.  In this case we used to adjust
  226.    indirect items's ih_free_space. Now ih_free_space is not
  227.    used, it would be ideal to write zeros to corresponding
  228.    unformatted node. For now i_size is considered as guard for
  229.    going out of file size */
  230. kunmap(page) ;
  231. return n_block_size - round_tail_len;
  232.     }
  233.     kunmap(page) ;
  234.     /* this will invalidate all the buffers in the page after
  235.     ** pos1
  236.     */
  237.     unmap_buffers(page, pos1) ;
  238.     // note: we have now the same as in above direct2indirect
  239.     // conversion: there are two keys which have matching first three
  240.     // key components. They only differ by the fouhth one.
  241.     /* We have inserted new direct item and must remove last
  242.        unformatted node. */
  243.     p_s_inode->i_blocks += (p_s_sb->s_blocksize / 512);
  244.     *p_c_mode = M_CUT;
  245.     /* we store position of first direct item in the in-core inode */
  246.     //mark_file_with_tail (p_s_inode, pos1 + 1);
  247.     p_s_inode->u.reiserfs_i.i_first_direct_byte = pos1 + 1;
  248.     return n_block_size - round_tail_len;
  249. }