/* path points to first direct item of the file regarless of how many of them are there */ int direct2indirect (struct reiserfs_transaction_handle *th, struct inode * inode, struct path * path, struct buffer_head * unbh, loff_t tail_offset) { struct super_block * sb = inode->i_sb; struct buffer_head *up_to_date_bh ; struct item_head * p_le_ih = PATH_PITEM_HEAD (path); unsigned long total_tail = 0 ; struct cpu_key end_key; /* Key to search for the last byte of the converted item. */ struct item_head ind_ih; /* new indirect item to be inserted or key of unfm pointer to be pasted */ int n_blk_size, n_retval; /* returned value for reiserfs_insert_item and clones */ struct unfm_nodeinfo unfm_ptr; /* Handle on an unformatted node that will be inserted in the tree. */ sb->u.reiserfs_sb.s_direct2indirect ++; n_blk_size = sb->s_blocksize; /* and key to search for append or insert pointer to the new unformatted node. */ copy_item_head (&ind_ih, p_le_ih); set_le_ih_k_offset (&ind_ih, tail_offset); set_le_ih_k_type (&ind_ih, TYPE_INDIRECT); /* Set the key to search for the place for new unfm pointer */ make_cpu_key (&end_key, inode, tail_offset, TYPE_INDIRECT, 4); // FIXME: we could avoid this if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) { reiserfs_warning ("PAP-14030: direct2indirect: " "pasted or inserted byte exists in the tree %K. " "Use fsck to repair.\n", &end_key); pathrelse(path); return -EIO; } p_le_ih = PATH_PITEM_HEAD (path); unfm_ptr.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr); unfm_ptr.unfm_freespace = 0; // ??? if ( is_statdata_le_ih (p_le_ih) ) { /* Insert new indirect item. */ set_ih_free_space (&ind_ih, 0); /* delete at nearest future */ put_ih_item_len( &ind_ih, UNFM_P_SIZE ); PATH_LAST_POSITION (path)++; n_retval = reiserfs_insert_item (th, path, &end_key, &ind_ih, (char *)&unfm_ptr); } else { /* Paste into last indirect item of an object. */ n_retval = reiserfs_paste_into_item(th, path, &end_key, (char *)&unfm_ptr, UNFM_P_SIZE); } if ( n_retval ) { return n_retval; } // note: from here there are two keys which have matching first // three key components. They only differ by the fourth one. /* Set the key to search for the direct items of the file */ make_cpu_key (&end_key, inode, max_reiserfs_offset (inode), TYPE_DIRECT, 4); /* Move bytes from the direct items to the new unformatted node and delete them. */ while (1) { int tail_size; /* end_key.k_offset is set so, that we will always have found last item of the file */ if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) reiserfs_panic (sb, "PAP-14050: direct2indirect: " "direct item (%K) not found", &end_key); p_le_ih = PATH_PITEM_HEAD (path); RFALSE( !is_direct_le_ih (p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset (p_le_ih) & (n_blk_size - 1)) + ih_item_len(p_le_ih) - 1; /* we only send the unbh pointer if the buffer is not up to date. ** this avoids overwriting good data from writepage() with old data ** from the disk or buffer cache ** Special case: unbh->b_page will be NULL if we are coming through ** DIRECT_IO handler here. */ if ( !unbh->b_page || buffer_uptodate(unbh) || Page_Uptodate(unbh->b_page)) { up_to_date_bh = NULL ; } else { up_to_date_bh = unbh ; } n_retval = reiserfs_delete_item (th, path, &end_key, inode, up_to_date_bh) ; total_tail += n_retval ; if (tail_size == n_retval) // done: file does not have direct items anymore break; } /* if we've copied bytes from disk into the page, we need to zero ** out the unused part of the block (it was not up to date before) ** the page is still kmapped (by whoever called reiserfs_get_block) */ if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1); memset(page_address(unbh->b_page) + pgoff, 0, n_blk_size - total_tail) ; } inode->u.reiserfs_i.i_first_direct_byte = U32_MAX; reiserfs_update_tail_transaction(inode); return 0; }
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, struct buffer_head *unbh, loff_t tail_offset) { struct super_block *sb = inode->i_sb; struct buffer_head *up_to_date_bh; struct item_head *p_le_ih = PATH_PITEM_HEAD(path); unsigned long total_tail = 0; struct cpu_key end_key; struct item_head ind_ih; int blk_size, retval; unp_t unfm_ptr; BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_direct2indirect++; blk_size = sb->s_blocksize; copy_item_head(&ind_ih, p_le_ih); set_le_ih_k_offset(&ind_ih, tail_offset); set_le_ih_k_type(&ind_ih, TYPE_INDIRECT); make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4); if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) { reiserfs_error(sb, "PAP-14030", "pasted or inserted byte exists in " "the tree %K. Use fsck to repair.", &end_key); pathrelse(path); return -EIO; } p_le_ih = PATH_PITEM_HEAD(path); unfm_ptr = cpu_to_le32(unbh->b_blocknr); if (is_statdata_le_ih(p_le_ih)) { set_ih_free_space(&ind_ih, 0); put_ih_item_len(&ind_ih, UNFM_P_SIZE); PATH_LAST_POSITION(path)++; retval = reiserfs_insert_item(th, path, &end_key, &ind_ih, inode, (char *)&unfm_ptr); } else { retval = reiserfs_paste_into_item(th, path, &end_key, inode, (char *)&unfm_ptr, UNFM_P_SIZE); } if (retval) { return retval; } make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT, 4); while (1) { int tail_size; if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) reiserfs_panic(sb, "PAP-14050", "direct item (%K) not found", &end_key); p_le_ih = PATH_PITEM_HEAD(path); RFALSE(!is_direct_le_ih(p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1)) + ih_item_len(p_le_ih) - 1; if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL; } else { up_to_date_bh = unbh; } retval = reiserfs_delete_item(th, path, &end_key, inode, up_to_date_bh); total_tail += retval; if (tail_size == retval) break; } if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1); char *kaddr = kmap_atomic(up_to_date_bh->b_page); memset(kaddr + pgoff, 0, blk_size - total_tail); kunmap_atomic(kaddr); } REISERFS_I(inode)->i_first_direct_byte = U32_MAX; return 0; }
/* Allocates blocks for a file to fulfil write request. Maps all unmapped but prepared pages from the list. Updates metadata with newly allocated blocknumbers as needed */ int reiserfs_allocate_blocks_for_region( struct reiserfs_transaction_handle *th, struct inode *inode, /* Inode we work with */ loff_t pos, /* Writing position */ int num_pages, /* number of pages write going to touch */ int write_bytes, /* amount of bytes to write */ struct page **prepared_pages, /* array of prepared pages */ int blocks_to_allocate /* Amount of blocks we need to allocate to fit the data into file */ ) { struct cpu_key key; // cpu key of item that we are going to deal with struct item_head *ih; // pointer to item head that we are going to deal with struct buffer_head *bh; // Buffer head that contains items that we are going to deal with __u32 * item; // pointer to item we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. reiserfs_blocknr_hint_t hint; // hint structure for block allocator. size_t res; // return value of various functions that we call. int curr_block; // current block used to keep track of unmapped blocks. int i; // loop counter int itempos; // position in item unsigned int from = (pos & (PAGE_CACHE_SIZE - 1)); // writing position in // first page unsigned int to = ((pos + write_bytes - 1) & (PAGE_CACHE_SIZE - 1)) + 1; /* last modified byte offset in last page */ __u64 hole_size ; // amount of blocks for a file hole, if it needed to be created. int modifying_this_item = 0; // Flag for items traversal code to keep track // of the fact that we already prepared // current block for journal int will_prealloc = 0; RFALSE(!blocks_to_allocate, "green-9004: tried to allocate zero blocks?"); /* only preallocate if this is a small write */ if (REISERFS_I(inode)->i_prealloc_count || (!(write_bytes & (inode->i_sb->s_blocksize -1)) && blocks_to_allocate < REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize)) will_prealloc = REISERFS_SB(inode->i_sb)->s_alloc_options.preallocsize; allocated_blocks = kmalloc((blocks_to_allocate + will_prealloc) * sizeof(b_blocknr_t), GFP_NOFS); /* First we compose a key to point at the writing position, we want to do that outside of any locking region. */ make_cpu_key (&key, inode, pos+1, TYPE_ANY, 3/*key length*/); /* If we came here, it means we absolutely need to open a transaction, since we need to allocate some blocks */ reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that. journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1); // Wish I know if this number enough reiserfs_update_inode_transaction(inode) ; /* Look for the in-tree position of our write, need path for block allocator */ res = search_for_position_by_key(inode->i_sb, &key, &path); if ( res == IO_ERROR ) { res = -EIO; goto error_exit; } /* Allocate blocks */ /* First fill in "hint" structure for block allocator */ hint.th = th; // transaction handle. hint.path = &path; // Path, so that block allocator can determine packing locality or whatever it needs to determine. hint.inode = inode; // Inode is needed by block allocator too. hint.search_start = 0; // We have no hint on where to search free blocks for block allocator. hint.key = key.on_disk_key; // on disk key of file. hint.block = inode->i_blocks>>(inode->i_sb->s_blocksize_bits-9); // Number of disk blocks this file occupies already. hint.formatted_node = 0; // We are allocating blocks for unformatted node. hint.preallocate = will_prealloc; /* Call block allocator to allocate blocks */ res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate); if ( res != CARRY_ON ) { if ( res == NO_DISK_SPACE ) { /* We flush the transaction in case of no space. This way some blocks might become free */ SB_JOURNAL(inode->i_sb)->j_must_wait = 1; restart_transaction(th, inode, &path); /* We might have scheduled, so search again */ res = search_for_position_by_key(inode->i_sb, &key, &path); if ( res == IO_ERROR ) { res = -EIO; goto error_exit; } /* update changed info for hint structure. */ res = reiserfs_allocate_blocknrs(&hint, allocated_blocks, blocks_to_allocate, blocks_to_allocate); if ( res != CARRY_ON ) { res = -ENOSPC; pathrelse(&path); goto error_exit; } } else { res = -ENOSPC; pathrelse(&path); goto error_exit; } } #ifdef __BIG_ENDIAN // Too bad, I have not found any way to convert a given region from // cpu format to little endian format { int i; for ( i = 0; i < blocks_to_allocate ; i++) allocated_blocks[i]=cpu_to_le32(allocated_blocks[i]); } #endif /* Blocks allocating well might have scheduled and tree might have changed, let's search the tree again */ /* find where in the tree our write should go */ res = search_for_position_by_key(inode->i_sb, &key, &path); if ( res == IO_ERROR ) { res = -EIO; goto error_exit_free_blocks; } bh = get_last_bh( &path ); // Get a bufferhead for last element in path. ih = get_ih( &path ); // Get a pointer to last item head in path. item = get_item( &path ); // Get a pointer to last item in path /* Let's see what we have found */ if ( res != POSITION_FOUND ) { /* position not found, this means that we might need to append file with holes first */ // Since we are writing past the file's end, we need to find out if // there is a hole that needs to be inserted before our writing // position, and how many blocks it is going to cover (we need to // populate pointers to file blocks representing the hole with zeros) { int item_offset = 1; /* * if ih is stat data, its offset is 0 and we don't want to * add 1 to pos in the hole_size calculation */ if (is_statdata_le_ih(ih)) item_offset = 0; hole_size = (pos + item_offset - (le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize))) >> inode->i_sb->s_blocksize_bits; }
/* * path points to first direct item of the file regardless of how many of * them are there */ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode, struct treepath *path, struct buffer_head *unbh, loff_t tail_offset) { struct super_block *sb = inode->i_sb; struct buffer_head *up_to_date_bh; struct item_head *p_le_ih = tp_item_head(path); unsigned long total_tail = 0; /* Key to search for the last byte of the converted item. */ struct cpu_key end_key; /* * new indirect item to be inserted or key * of unfm pointer to be pasted */ struct item_head ind_ih; int blk_size; /* returned value for reiserfs_insert_item and clones */ int retval; /* Handle on an unformatted node that will be inserted in the tree. */ unp_t unfm_ptr; BUG_ON(!th->t_trans_id); REISERFS_SB(sb)->s_direct2indirect++; blk_size = sb->s_blocksize; /* * and key to search for append or insert pointer to the new * unformatted node. */ copy_item_head(&ind_ih, p_le_ih); set_le_ih_k_offset(&ind_ih, tail_offset); set_le_ih_k_type(&ind_ih, TYPE_INDIRECT); /* Set the key to search for the place for new unfm pointer */ make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4); /* FIXME: we could avoid this */ if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) { reiserfs_error(sb, "PAP-14030", "pasted or inserted byte exists in " "the tree %K. Use fsck to repair.", &end_key); pathrelse(path); return -EIO; } p_le_ih = tp_item_head(path); unfm_ptr = cpu_to_le32(unbh->b_blocknr); if (is_statdata_le_ih(p_le_ih)) { /* Insert new indirect item. */ set_ih_free_space(&ind_ih, 0); /* delete at nearest future */ put_ih_item_len(&ind_ih, UNFM_P_SIZE); PATH_LAST_POSITION(path)++; retval = reiserfs_insert_item(th, path, &end_key, &ind_ih, inode, (char *)&unfm_ptr); } else { /* Paste into last indirect item of an object. */ retval = reiserfs_paste_into_item(th, path, &end_key, inode, (char *)&unfm_ptr, UNFM_P_SIZE); } if (retval) { return retval; } /* * note: from here there are two keys which have matching first * three key components. They only differ by the fourth one. */ /* Set the key to search for the direct items of the file */ make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT, 4); /* * Move bytes from the direct items to the new unformatted node * and delete them. */ while (1) { int tail_size; /* * end_key.k_offset is set so, that we will always have found * last item of the file */ if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) reiserfs_panic(sb, "PAP-14050", "direct item (%K) not found", &end_key); p_le_ih = tp_item_head(path); RFALSE(!is_direct_le_ih(p_le_ih), "vs-14055: direct item expected(%K), found %h", &end_key, p_le_ih); tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1)) + ih_item_len(p_le_ih) - 1; /* * we only send the unbh pointer if the buffer is not * up to date. this avoids overwriting good data from * writepage() with old data from the disk or buffer cache * Special case: unbh->b_page will be NULL if we are coming * through DIRECT_IO handler here. */ if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL; } else { up_to_date_bh = unbh; } retval = reiserfs_delete_item(th, path, &end_key, inode, up_to_date_bh); total_tail += retval; /* done: file does not have direct items anymore */ if (tail_size == retval) break; } /* * if we've copied bytes from disk into the page, we need to zero * out the unused part of the block (it was not up to date before) */ if (up_to_date_bh) { unsigned pgoff = (tail_offset + total_tail - 1) & (PAGE_SIZE - 1); char *kaddr = kmap_atomic(up_to_date_bh->b_page); memset(kaddr + pgoff, 0, blk_size - total_tail); kunmap_atomic(kaddr); } REISERFS_I(inode)->i_first_direct_byte = U32_MAX; return 0; }