diff -urN v2.4.13p5/fs/reiserfs/bitmap.c linux/fs/reiserfs/bitmap.c
--- v2.4.13p5/fs/reiserfs/bitmap.c Fri Oct 19 15:00:59 2001
+++ linux/fs/reiserfs/bitmap.c Fri Oct 19 15:04:17 2001
@@ -392,13 +392,14 @@
** has allocated it. loop around and try again
*/
if (reiserfs_test_and_set_le_bit (j, SB_AP_BITMAP (s)[i]->b_data)) {
- reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free");
+ reiserfs_warning("vs-4150: reiserfs_new_blocknrs, block not free\n");
reiserfs_restore_prepared_buffer(s, SB_AP_BITMAP(s)[i]) ;
amount_needed++ ;
continue ;
}
journal_mark_dirty (th, s, SB_AP_BITMAP (s)[i]);
*free_blocknrs = search_start ;
+
free_blocknrs ++;
}
@@ -464,6 +465,7 @@
int allocated[PREALLOCATION_SIZE];
int blks;
+
if (!reiserfs_no_border(th->t_super)) {
/* we default to having the border at the 10% mark of the disk. This
** is an arbitrary decision and it needs tuning. It also needs a limit
@@ -539,6 +541,7 @@
return ret;
}
+
/* take a block off the prealloc list and return it -Hans */
if (p_s_inode->u.reiserfs_i.i_prealloc_count > 0) {
p_s_inode->u.reiserfs_i.i_prealloc_count--;
@@ -606,6 +609,8 @@
search_start = *free_blocknrs;
*free_blocknrs = 0;
}
+
+
p_s_inode->u.reiserfs_i.i_prealloc_count = blks;
*free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block;
p_s_inode->u.reiserfs_i.i_prealloc_block++;
diff -urN v2.4.13p5/fs/reiserfs/do_balan.c linux/fs/reiserfs/do_balan.c
--- v2.4.13p5/fs/reiserfs/do_balan.c Fri Oct 19 15:00:59 2001
+++ linux/fs/reiserfs/do_balan.c Fri Oct 19 15:10:51 2001
@@ -524,9 +524,6 @@
bi.bi_bh, n + item_pos - ret_val, pos_in_item, 1,
(struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]
);
- /* if appended item is indirect item, put unformatted node into un list */
- if (is_indirect_le_ih (pasted))
- set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
tb->insert_size[0] = 0;
zeros_num = 0;
}
@@ -729,7 +726,6 @@
RFALSE( n_rem,
"PAP-12160: paste more than one unformatted node pointer");
-
-
-
-/* we need to allocate a block for new unformatted node. Try to figure out
- what point in bitmap reiserfs_new_blocknrs should start from. */
-static b_blocknr_t find_tag (struct buffer_head * bh, struct item_head * ih,
- __u32 * item, int pos_in_item)
-{
- __u32 block ;
- if (!is_indirect_le_ih (ih))
- /* something more complicated could be here */
- return bh->b_blocknr;
-
- /* for indirect item: go to left and look for the first non-hole entry in
- the indirect item */
- if (pos_in_item == I_UNFM_NUM (ih))
- pos_in_item --;
- while (pos_in_item >= 0) {
- block = get_block_num(item, pos_in_item) ;
- if (block)
- return block ;
- pos_in_item --;
- }
- return bh->b_blocknr;
-}
-
-
/* reiserfs_get_block does not need to allocate a block only if it has been
done already or non-hole position has been found in the indirect item */
static inline int allocation_needed (int retval, b_blocknr_t allocated,
@@ -496,6 +469,7 @@
unsigned long tag,
int flags) {
+ *allocated_block_nr = 0;
#ifdef REISERFS_PREALLOCATE
if (!(flags & GET_BLOCK_NO_ISEM)) {
return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr, tag);
@@ -503,6 +477,346 @@
#endif
return reiserfs_new_unf_blocknrs (th, allocated_block_nr, tag);
}
+
+
+/* this returns either ok, repeat or no disk space */
+static inline int allocate_block (struct reiserfs_transaction_handle *th,
+ struct inode * inode,
+ unsigned long * pblock,
+ unsigned long search_start,
+ struct path * path,
+ int create_flag)
+{
+ int retval;
+ int fs_gen;
+ struct item_head tmp_ih;
+
+
+ fs_gen = get_generation (inode->i_sb);
+ tmp_ih = *get_ih (path);
+
+ retval = _allocate_block(th, inode, pblock, search_start, create_flag);
+ if (retval == CARRY_ON) {
+ if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, path))
+ return REPEAT_SEARCH;
+ return CARRY_ON;
+ }
+
+ /* restart the transaction to give the journal a chance to free some
+ ** blocks. releases the path, so we have to go back to research if we
+ ** succeed on the second try
+ */
+ restart_transaction(th, inode, path) ;
+ retval = _allocate_block(th, inode,pblock,search_start,create_flag) ;
+ if (retval == NO_DISK_SPACE)
+ return NO_DISK_SPACE;
+
+ return REPEAT_SEARCH;
+}
+
+
+/* path points to an indirect item */
+static unsigned long indirect_determine_search_start (struct path * path)
+{
+ __u32 * item;
+ struct item_head * ih;
+ int pos, i;
+
+
+ ih = get_ih (path);
+ item = get_item (path);
+
+ /* this is position in the indirect item where we will put new unformatted
+ * node pointer */
+ pos = path->pos_in_item;
+
+ for (i = pos - 1; i >= 0; i --) {
+ if (item [i])
+ return le32_to_cpu (item [i]);
+ }
+
+ /* all unfm ptrs are 0 */
+ return get_last_bh (path)->b_blocknr;
+}
+
+
+/* path either points to stat data or to direct item */
+static unsigned long direct_determine_search_start (struct path * path)
+{
+ return get_last_bh (path)->b_blocknr;
+}
+
+
+
+/* initially path points to a hole in an indirect item which is to be
+ plugged */
+static int plug_the_hole (struct reiserfs_transaction_handle * th,
+ struct path * path,
+ struct cpu_key * key,
+ struct inode * inode,
+ struct buffer_head * bh_result,
+ int create_flag)
+{
+ int retval;
+ unsigned long block, search_start;
+ int fs_gen;
+ struct item_head tmp_ih;
+ struct buffer_head * bh;
+ __u32 * item;
+
+
+ /* search_start is first non-zero unformatted node pointer */
+ search_start = indirect_determine_search_start (path);
+
+ retval = allocate_block (th, inode, &block, search_start, path, create_flag);
+ if (retval == NO_DISK_SPACE)
+ return -ENOSPC;
+
+ while (1) {
+ if (retval == REPEAT_SEARCH) {
+ retval = search_for_position_by_key (inode->i_sb, key, path);
+ if (retval != POSITION_FOUND) {
+ /* something wrong happened */
+ reiserfs_warning ("vs-13005: plug the hole: "
+ "could not found the hole %K again (%d)\n",
+ key, retval);
+ reiserfs_free_block (th, block);
+ pathrelse (path);
+ return -EIO;
+ }
+ }
+
+ bh = get_last_bh (path);
+ item = get_item (path);
+ if (item [path->pos_in_item]) {
+ reiserfs_warning ("vs-13010: plug the hole: "
+ "someone passed us by and plugged our hole %K with %lu\n",
+ key, le32_to_cpu (item [path->pos_in_item]));
+ reiserfs_free_block (th, block);
+ pathrelse (path);
+ return -EIO;
+ }
+
+ fs_gen = get_generation (inode->i_sb);
+ tmp_ih = *get_ih (path);
+
+ reiserfs_prepare_for_journal(inode->i_sb, bh, 1) ;
+ if (!fs_changed (fs_gen, inode->i_sb) || !item_moved (&tmp_ih, path)) {
+ /* ok, new block is allocated, node which will contain pointer to
+ is prepared, so, complete the job */
+ break;
+ }
+
+ reiserfs_restore_prepared_buffer(inode->i_sb, bh) ;
+ retval = REPEAT_SEARCH;
+ }
+
+ bh_result->b_state |= (1UL << BH_New) ;
+ set_block_dev_mapped(bh_result, block, inode) ;
+
+ item[path->pos_in_item] = cpu_to_le32 (block);
+ journal_mark_dirty (th, inode->i_sb, bh);
+
+ inode->i_blocks += (inode->i_sb->s_blocksize / 512) ;
+ reiserfs_update_sd(th, inode) ;
+ pathrelse (path);
+
+ return 0;
+}
+
+
+/* path points to stat data of this file */
+static int insert_first_unfm_ptr (struct reiserfs_transaction_handle * th,
+ struct path * path,
+ struct cpu_key * key,
+ struct inode * inode,
+ struct buffer_head * bh_result,
+ int create_flag)
+{
+ int retval;
+ unsigned long block, search_start;
+ struct cpu_key tmp_key;
+ struct item_head tmp_ih;
+ struct item_head * ih;
+ __u32 unp;
+
+
+ search_start = direct_determine_search_start (path);
+
+ retval = allocate_block (th, inode, &block, search_start, path, create_flag);
+ if (retval == NO_DISK_SPACE)
+ return -ENOSPC;
+
+ if (retval == REPEAT_SEARCH) {
+ retval = search_for_position_by_key (inode->i_sb, key, path);
+ if (retval == POSITION_FOUND) {
+ /* someone could come along, pass us by and put a hole
+ there. Return -EAGAIN to have plug_the_hole to deal with that
+ hole */
+ retval = -EAGAIN;
+ goto out;
+ }
+ }
+
+ ih = get_ih (path);
+ if (retval != POSITION_NOT_FOUND || !is_statdata_le_ih (ih) ||
+ not_of_one_file (&ih->ih_key, key)) {
+ retval = -EIO;
+ goto out;
+ }
+
+ /* key of item to be inserted */
+ tmp_key = *key;
+ /* ih of indirect item to be inserted */
+ make_le_item_head (&tmp_ih, key, inode_items_version (inode), 1, TYPE_INDIRECT,
+ UNFM_P_SIZE, 0/* free_space */);
+ /* item itself */
+ unp = cpu_to_le32 (block);
+ /* point for insertion */
+ PATH_LAST_POSITION(path) ++;
+
+ retval = reiserfs_insert_item (th, path, &tmp_key, &tmp_ih, (char *)&unp);
+ if (retval) {
+ if (retval == -EEXIST)
+ /* someone could come along, pass us by and create a hole
+ there. Return -EAGAIN to have plug_the_hole to deal with that
+ hole */
+ retval = -EAGAIN;
+ goto out;
+ }
+
+ /* ok, the unformatted node pointer is added */
+ inode->i_blocks += inode->i_sb->s_blocksize / 512;
+ set_block_dev_mapped (bh_result, block, inode);
+ bh_result->b_state |= (1UL << BH_New);
+ reiserfs_update_sd(th, inode) ;
+ return 0;
+
+ out:
+ reiserfs_free_block (th, block);
+ pathrelse (path);
+ return retval;
+}
+
+
+static int convert_direct_item (struct reiserfs_transaction_handle * th,
+ struct path * path,
+ struct cpu_key * key,
+ struct inode * inode,
+ struct buffer_head * bh_result,
+ int create_flag)
+{
+ int retval;
+ unsigned long block, search_start;
+
+
+ search_start = direct_determine_search_start (path);
+
+ retval = allocate_block (th, inode, &block, search_start, path, create_flag);
+ if (retval == NO_DISK_SPACE)
+ return -ENOSPC;
+
+
+ set_block_dev_mapped (bh_result, block, inode);
+
+ /* direct2indirect starts with search_by_key anyway */
+ retval = direct2indirect (th, inode, path, bh_result, cpu_key_k_offset (key));
+ /* it is important the mark_buffer_uptodate is done after the
+ ** direct2indirect. The buffer might contain valid data newer than the
+ ** data on disk (read by readpage, changed, and then sent here by
+ ** writepage). direct2indirect needs to know if unbh was already up to
+ ** date, so it can decide if the data in unbh needs to be replaced with
+ ** data from the disk
+ */
+ mark_buffer_uptodate (bh_result, 1);
+ if (retval) {
+ reiserfs_free_block (th, block);
+ return retval;
+ }
+ /* we've converted the tail, so we must flush bh_result before the
+ ** transaction commits
+ */
+ add_to_flushlist(inode, bh_result) ;
+
+ /* mark it dirty now to prevent commit_write from adding this buffer to
+ ** the inode's dirty buffer list
+ */
+ __mark_buffer_dirty(bh_result) ;
+
+ return 0;
+}
+
+
+
+/* this has to paste unformatted node pointer which will point to a block
+ reiserfs_get_block is called for */
+static int paste_unfm_ptr (struct reiserfs_transaction_handle * th,
+ struct path * path,
+ struct cpu_key * key,
+ struct inode * inode,
+ struct buffer_head * bh_result,
+ int create_flag)
+{
+ int retval;
+ unsigned long block, search_start;
+ __u32 unp;
+ struct item_head * ih;
+
+
+ /* determine a point in the bitmaps where to start looking for free block
+ from */
+ search_start = indirect_determine_search_start (path);
+
+ retval = allocate_block (th, inode, &block, search_start, path, create_flag);
+ if (retval == NO_DISK_SPACE)
+ return -ENOSPC;
+
+ if (retval == REPEAT_SEARCH) {
+ retval = search_for_position_by_key (inode->i_sb, key, path);
+ if (retval == POSITION_FOUND) {
+ /* someone could come along, passde us by and appended zero (!zero is
+ impossible) there. Return -EAGAIN to have plug_the_hole to deal
+ with that hole */
+ retval = -EAGAIN;
+ goto out;
+ }
+ }
+
+ ih = get_ih (path);
+ if (retval != POSITION_NOT_FOUND || !is_indirect_le_ih (ih) ||
+ not_of_one_file (&ih->ih_key, key)) {
+ retval = -EIO;
+ goto out;
+ }
+
+ /* thing to be appended */
+ unp = cpu_to_le32 (block);
+
+ retval = reiserfs_paste_into_item (th, path, key, (char *)&unp, UNFM_P_SIZE);
+ if (retval) {
+ if (retval == -EEXIST)
+ /* someone could come along, pass us by and put a hole
+ there. Return -EAGAIN to have plug_the_hole to deal with that
+ hole */
+ retval = -EAGAIN;
+ goto out;
+ }
+
+ /* ok, the unformatted node pointer is added */
+ inode->i_blocks += inode->i_sb->s_blocksize / 512;
+ set_block_dev_mapped (bh_result, block, inode);
+ bh_result->b_state |= (1UL << BH_New);
+ reiserfs_update_sd(th, inode) ;
+ return 0;
+
+ out:
+ reiserfs_free_block (th, block);
+ pathrelse (path);
+ return retval;
+}
+
+
+
//
// initially this function was derived from ext2's analog and evolved
// as the prototype did. You'll need to look at the ext2 version to
@@ -512,17 +826,13 @@
int reiserfs_get_block (struct inode * inode, long block,
struct buffer_head * bh_result, int create)
{
- int repeat, retval;
- unsigned long tag;
- b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is unsigned long
+ int retval;
INITIALIZE_PATH(path);
int pos_in_item;
- struct cpu_key key;
- struct buffer_head * bh, * unbh = 0;
+ struct cpu_key key, tmp_key;
+ struct buffer_head * bh;
struct item_head * ih, tmp_ih;
__u32 * item;
- int done;
- int fs_gen;
int windex ;
struct reiserfs_transaction_handle th ;
/* space reserved in transaction batch:
@@ -533,7 +843,8 @@
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1;
int version;
int transaction_started = 0 ;
- loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
+ loff_t new_offset = ((long)block << inode->i_sb->s_blocksize_bits) + 1 ;
+ __u32 unfm_ptr;
- if (allocation_needed (retval, allocated_block_nr, ih, item, pos_in_item)) {
- /* we have to allocate block for the unformatted node */
- tag = find_tag (bh, ih, item, pos_in_item);
- if (!transaction_started) {
- pathrelse(&path) ;
- journal_begin(&th, inode->i_sb, jbegin_count) ;
- reiserfs_update_inode_transaction(inode) ;
- transaction_started = 1 ;
- goto research ;
+ while (1) {
+ retval = search_for_position_by_key (inode->i_sb, &key, &path);
+ if (retval == IO_ERROR || retval == FILE_NOT_FOUND) {
+ /* FILE_NOT_FOUND means that something is wrong - return -EIO
+ * then */
+ retval = -EIO;
+ break;
+ }
+
+ bh = get_last_bh (&path);
+ ih = get_ih (&path);
+ item = get_item (&path);
+ pos_in_item = path.pos_in_item;
+
+ if (indirect_item_found (retval, ih)) {
+ /* required position found in an indirect item */
+ if (item[pos_in_item]) {
+ set_block_dev_mapped(bh_result, le32_to_cpu (item[pos_in_item]), inode);
+ pathrelse (&path);
+ retval = 0;
+ /* corresponding slot is not 0, so new blocks were not added
+ ** to the file there is no need to make sure the inode is
+ ** updated with this transaction (FIXME: reiserfs_update_sd is
+ ** called at the end, btw)
+ */
+ break;
}
-
- repeat = _allocate_block(&th, inode, &allocated_block_nr, tag, create);
-
- if (repeat == NO_DISK_SPACE) {
- /* restart the transaction to give the journal a chance to free
- ** some blocks. releases the path, so we have to go back to
- ** research if we succeed on the second try
- */
- restart_transaction(&th, inode, &path) ;
- repeat = _allocate_block(&th, inode,&allocated_block_nr,tag,create);
-
- if (repeat != NO_DISK_SPACE) {
- goto research ;
- }
- retval = -ENOSPC;
- goto failure;
+ /* found cell in indirect item is 0 */
+ retval = plug_the_hole (&th, &path, &key, inode, bh_result, create);
+ break;
+ }
+ else if (is_statdata_le_ih (ih)) {
+ /* stat data is the only item of this file */
+ if (cpu_key_k_offset (&key) == 1) {
+ /* we are asked for this block */
+ retval = insert_first_unfm_ptr (&th, &path, &key, inode, bh_result, create);
+ if (retval == -EAGAIN)
+ /* someone passed us by and inserted this pointer first */
+ continue;
+ /* ok or error - we are done */
+ break;
}
-
- if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
- goto research;
+ /* key of item to be inserted */
+ tmp_key = key;
+ set_cpu_key_k_offset (&tmp_key, 1);
+
+ /* insert indirect item with one zero pointer */
+ make_le_item_head (&tmp_ih, &key, version, 1, TYPE_INDIRECT,
+ UNFM_P_SIZE, 0/* free_space */);
+
+ /* item body */
+ unfm_ptr = cpu_to_le32 (0);
+ PATH_LAST_POSITION(&path) ++;
+ retval = reiserfs_insert_item (&th, &path, &tmp_key, &tmp_ih, (char *)&unfm_ptr);
+ if (retval == -ENOSPC || retval == -EIO)
+ break;
+
+ /* 0 or -EEXIST are ok, because either we have added a 0 slot or
+ someone else did that */
+ }
+ else if (is_indirect_le_ih (ih)) {
+ /* we have to append unfm pointer */
+ tmp_key = key;
+ set_cpu_key_k_offset (&tmp_key,
+ le_ih_k_offset (ih) + op_bytes_number (ih, inode->i_sb->s_blocksize));
+
+ if (cpu_key_k_offset (&tmp_key) == cpu_key_k_offset (&key)) {
+ /* we are asked for this block */
+ retval = paste_unfm_ptr (&th, &path, &key, inode, bh_result, create);
+ if (retval == -EAGAIN)
+ continue;
+ break;
}
- }
- if (indirect_item_found (retval, ih)) {
- b_blocknr_t unfm_ptr;
- /* 'block'-th block is in the file already (there is
- corresponding cell in some indirect item). But it may be
- zero unformatted node pointer (hole) */
- unfm_ptr = get_block_num (item, pos_in_item);
- if (unfm_ptr == 0) {
- /* use allocated block to plug the hole */
- reiserfs_prepare_for_journal(inode->i_sb, bh, 1) ;
- if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {
- reiserfs_restore_prepared_buffer(inode->i_sb, bh) ;
- goto research;
- }
- bh_result->b_state |= (1UL << BH_New);
- put_block_num(item, pos_in_item, allocated_block_nr) ;
- unfm_ptr = allocated_block_nr;
- journal_mark_dirty (&th, inode->i_sb, bh);
- inode->i_blocks += (inode->i_sb->s_blocksize / 512) ;
- reiserfs_update_sd(&th, inode) ;
+ unfm_ptr = cpu_to_le32 (0);
+ retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)&unfm_ptr, UNFM_P_SIZE);
+ if (retval == -ENOSPC || retval == -EIO)
+ break;
+ /* 0 or -EEXIST are ok, because either we have added a 0 slot or
+ someone else did that */
+ }
+ else if (is_direct_le_ih (ih)) {
+ /* direct item has to be converted */
+ loff_t tail_offset;
+ if (retval == POSITION_FOUND) {
+ /* we are asked for this block */
+ retval = convert_direct_item (&th, &path, &key, inode, bh_result, create);
+ break;
}
- set_block_dev_mapped(bh_result, unfm_ptr, inode);
- pathrelse (&path);
- pop_journal_writer(windex) ;
- if (transaction_started)
- journal_end(&th, inode->i_sb, jbegin_count) ;
-
- unlock_kernel() ;
-
- /* the item was found, so new blocks were not added to the file
- ** there is no need to make sure the inode is updated with this
- ** transaction
- */
- return 0;
- }
+
+ /* offset of the first direct item of the tail */
+ tail_offset = ((le_ih_k_offset (ih) - 1) & ~(inode->i_sb->s_blocksize - 1)) + 1;
+
+ /* we have to padd file tail stored in direct item(s) up to block
+ size and convert it to unformatted node. FIXME: this should
+ also get into page cache */
- if (!transaction_started) {
- /* if we don't pathrelse, we could vs-3050 on the buffer if
- ** someone is waiting for it (they can't finish until the buffer
- ** is released, we can start a new transaction until they finish)
- */
pathrelse(&path) ;
- journal_begin(&th, inode->i_sb, jbegin_count) ;
- reiserfs_update_inode_transaction(inode) ;
- transaction_started = 1 ;
- goto research;
- }
+ journal_end(&th, inode->i_sb, jbegin_count) ;
+ transaction_started = 0 ;
- /* desired position is not found or is in the direct item. We have
- to append file with holes up to 'block'-th block converting
- direct items to indirect one if necessary */
- done = 0;
- do {
- if (is_statdata_le_ih (ih)) {
- __u32 unp = 0;
- struct cpu_key tmp_key;
-
- /* indirect item has to be inserted */
- make_le_item_head (&tmp_ih, &key, version, 1, TYPE_INDIRECT,
- UNFM_P_SIZE, 0/* free_space */);
-
- if (cpu_key_k_offset (&key) == 1) {
- /* we are going to add 'block'-th block to the file. Use
- allocated block for that */
- unp = cpu_to_le32 (allocated_block_nr);
- set_block_dev_mapped (bh_result, allocated_block_nr, inode);
- bh_result->b_state |= (1UL << BH_New);
- done = 1;
- }
- tmp_key = key; // ;)
- set_cpu_key_k_offset (&tmp_key, 1);
- PATH_LAST_POSITION(&path) ++;
-
- retval = reiserfs_insert_item (&th, &path, &tmp_key, &tmp_ih, (char *)&unp);
- if (retval) {
- reiserfs_free_block (&th, allocated_block_nr);
- goto failure; // retval == -ENOSPC or -EIO or -EEXIST
- }
- if (unp)
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
- //mark_tail_converted (inode);
- } else if (is_direct_le_ih (ih)) {
- /* direct item has to be converted */
- loff_t tail_offset;
-
- tail_offset = ((le_ih_k_offset (ih) - 1) & ~(inode->i_sb->s_blocksize - 1)) + 1;
- if (tail_offset == cpu_key_k_offset (&key)) {
- /* direct item we just found fits into block we have
- to map. Convert it into unformatted node: use
- bh_result for the conversion */
- set_block_dev_mapped (bh_result, allocated_block_nr, inode);
- unbh = bh_result;
- done = 1;
- } else {
- /* we have to padd file tail stored in direct item(s)
- up to block size and convert it to unformatted
- node. FIXME: this should also get into page cache */
-
- pathrelse(&path) ;
- journal_end(&th, inode->i_sb, jbegin_count) ;
- transaction_started = 0 ;
-
- retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
- if (retval) {
- printk("clm-6004: convert tail failed inode %lu, error %d\n", inode->i_ino, retval) ;
- if (allocated_block_nr)
- reiserfs_free_block (&th, allocated_block_nr);
- goto failure ;
- }
- goto research ;
- }
- retval = direct2indirect (&th, inode, &path, unbh, tail_offset);
- /* it is important the mark_buffer_uptodate is done after
- ** the direct2indirect. The buffer might contain valid
- ** data newer than the data on disk (read by readpage, changed,
- ** and then sent here by writepage). direct2indirect needs
- ** to know if unbh was already up to date, so it can decide
- ** if the data in unbh needs to be replaced with data from
- ** the disk
- */
- mark_buffer_uptodate (unbh, 1);
- if (retval) {
- reiserfs_free_block (&th, allocated_block_nr);
- goto failure;
- }
- /* we've converted the tail, so we must
- ** flush unbh before the transaction commits
- */
- add_to_flushlist(inode, unbh) ;
+ retval = convert_tail_for_hole(inode, bh_result, tail_offset) ;
+ if (retval)
+ break;
- /* mark it dirty now to prevent commit_write from adding
- ** this buffer to the inode's dirty buffer list
- */
- __mark_buffer_dirty(unbh) ;
-
- //inode->i_blocks += inode->i_sb->s_blocksize / 512;
- //mark_tail_converted (inode);
- } else {
- /* append indirect item with holes if needed, when appending
- pointer to 'block'-th block use block, which is already
- allocated */
- struct cpu_key tmp_key;
- struct unfm_nodeinfo un = {0, 0};
-
- RFALSE( pos_in_item != ih_item_len(ih) / UNFM_P_SIZE,
- "vs-804: invalid position for append");
- /* indirect item has to be appended, set up key of that position */
- make_cpu_key (&tmp_key, inode,
- le_key_k_offset (version, &(ih->ih_key)) + op_bytes_number (ih, inode->i_sb->s_blocksize),
- //pos_in_item * inode->i_sb->s_blocksize,
- TYPE_INDIRECT, 3);// key type is unimportant
-
- if (cpu_key_k_offset (&tmp_key) == cpu_key_k_offset (&key)) {
- /* we are going to add target block to the file. Use allocated
- block for that */
- un.unfm_nodenum = cpu_to_le32 (allocated_block_nr);
- set_block_dev_mapped (bh_result, allocated_block_nr, inode);
- bh_result->b_state |= (1UL << BH_New);
- done = 1;
- } else {
- /* paste hole to the indirect item */
- }
- retval = reiserfs_paste_into_item (&th, &path, &tmp_key, (char *)&un, UNFM_P_SIZE);
- if (retval) {
- reiserfs_free_block (&th, allocated_block_nr);
- goto failure;
- }
- if (un.unfm_nodenum)
- inode->i_blocks += inode->i_sb->s_blocksize / 512;
- //mark_tail_converted (inode);
- }
-
- if (done == 1)
- break;
+ } else {
+ reiserfs_warning ("vs-13015: item of unexpected type found %h\n", ih);
+ pathrelse (&path);
+ retval = -EIO;
+ break;
+ }
- /* this loop could log more blocks than we had originally asked
- ** for. So, we have to allow the transaction to end if it is
- ** too big or too full. Update the inode so things are
- ** consistent if we crash before the function returns
- **
- ** release the path so that anybody waiting on the path before
- ** ending their transaction will be able to continue.
- */
- if (journal_transaction_should_end(&th, th.t_blocks_allocated)) {
- restart_transaction(&th, inode, &path) ;
- }
- /* inserting indirect pointers for a hole can take a
- ** long time. reschedule if needed
- */
- if (current->need_resched)
- schedule() ;
+ /* this loop could log more blocks than we had originally asked
+ ** for. So, we have to allow the transaction to end if it is
+ ** too big or too full. Update the inode so things are
+ ** consistent if we crash before the function returns
+ **
+ ** release the path so that anybody waiting on the path before
+ ** ending their transaction will be able to continue.
+ */
+ if (journal_transaction_should_end(&th, th.t_blocks_allocated)) {
+ restart_transaction(&th, inode, &path) ;
+ }
+ /* inserting indirect pointers for a hole can take a
+ ** long time. reschedule if needed
+ */
+ if (current->need_resched)
+ schedule() ;
+
+ }
diff -urN v2.4.13p5/fs/reiserfs/stree.c linux/fs/reiserfs/stree.c
--- v2.4.13p5/fs/reiserfs/stree.c Fri Oct 19 15:00:59 2001
+++ linux/fs/reiserfs/stree.c Fri Oct 19 15:04:56 2001
@@ -1892,7 +1892,7 @@
goto error_out ;
}
if (retval == POSITION_FOUND) {
- reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists", p_s_key);
+ reiserfs_warning ("PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists\n", p_s_key);
retval = -EEXIST ;
goto error_out ;
}
diff -urN v2.4.13p5/fs/reiserfs/tail_conversion.c linux/fs/reiserfs/tail_conversion.c
--- v2.4.13p5/fs/reiserfs/tail_conversion.c Fri Oct 19 15:00:59 2001
+++ linux/fs/reiserfs/tail_conversion.c Fri Oct 19 15:04:56 2001
@@ -30,9 +30,8 @@
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. */
+ __u32 unfm_ptr; /* Handle on an unformatted node that will be inserted in
+ the tree. */
sb->u.reiserfs_sb.s_direct2indirect ++;
@@ -48,16 +47,18 @@
/* 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_panic (sb, "PAP-14030: direct2indirect: "
- "pasted or inserted byte exists in the tree");
+ if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) {
+ pathrelse (path);
+ reiserfs_warning ("PAP-14030: direct2indirect: "
+ "conversion is done somewhere else\n");
+ return -EEXIST;
+ }
+
+ //printk ("removing the tail\n");
// note: from here there are two keys which have matching first
// three key components. They only differ by the fourth one.
@@ -88,9 +91,12 @@
/* 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);
+ if ( search_for_position_by_key (sb, &end_key, path) == POSITION_FOUND ) {
+ reiserfs_warning ("PAP-14050: direct2indirect: "
+ "direct item (%k) not found\n", &end_key);
+ pathrelse (path);
+ return -EIO;
+ }
p_le_ih = PATH_PITEM_HEAD (path);
RFALSE( !is_direct_le_ih (p_le_ih),
"vs-14055: direct item expected(%k), found %h",
@@ -109,6 +115,8 @@
}
n_retval = reiserfs_delete_item (th, path, &end_key, inode,
up_to_date_bh) ;
+
+ //reiserfs_warning ("delete: %K, retval %d\n", &end_key, n_retval);
total_tail += n_retval ;
if (tail_size == n_retval)
diff -urN v2.4.13p5/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h
--- v2.4.13p5/include/linux/reiserfs_fs.h Fri Oct 19 15:01:02 2001
+++ linux/include/linux/reiserfs_fs.h Fri Oct 19 15:04:56 2001
@@ -177,17 +177,6 @@
typedef unsigned long b_blocknr_t;
typedef __u32 unp_t;
- /* who is responsible for this
- completely uncommented struct? */
-struct unfm_nodeinfo {
- /* This is what? */
- unp_t unfm_nodenum;
- /* now this I know what it is, and
- most of the people on our project
- know what it is, but I bet nobody
- new I hire will have a clue. */
- unsigned short unfm_freespace;
-};
/* when reiserfs_file_write is called with a byte count >= MIN_PACK_ON_CLOSE,
@@ -1270,6 +1259,7 @@
#define get_item(path) ((void *)B_N_PITEM(PATH_PLAST_BUFFER(path), PATH_LAST_POSITION (path)))
#define item_moved(ih,path) comp_items(ih, path)
#define path_changed(ih,path) comp_items (ih, path)
+#define path_empty(path) ((path)->path_length == ILLEGAL_PATH_ELEMENT_OFFSET)
/*#define COMP_KEYS(p_s_key1, p_s_key2) comp_keys((unsigned long *)(p_s_key1), (unsigned long *)(p_s_key2))
#define COMP_SHORT_KEYS(p_s_key1, p_s_key2) comp_short_keys((unsigned long *)(p_s_key1), (unsigned long *)(p_s_key2))*/