err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); 
err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); 
static 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    __le32 * 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.    res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough    if (res)        goto error_exit;    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;	    res = restart_transaction(th, inode, &path);            if (res)                goto error_exit;	    /* 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;	}	if ( hole_size > 0 ) {	    int to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE ); // How much data to insert first time.	    /* area filled with zeroes, to supply as list of zero blocknumbers	       We allocate it outside of loop just in case loop would spin for	       several iterations. */	    char *zeros = kmalloc(to_paste*UNFM_P_SIZE, GFP_ATOMIC); // We cannot insert more than MAX_ITEM_LEN bytes anyway.	    if ( !zeros ) {		res = -ENOMEM;		goto error_exit_free_blocks;	    }	    memset ( zeros, 0, to_paste*UNFM_P_SIZE);	    do {		to_paste = min_t(__u64, hole_size, MAX_ITEM_LEN(inode->i_sb->s_blocksize)/UNFM_P_SIZE );		if ( is_indirect_le_ih(ih) ) {		    /* Ok, there is existing indirect item already. Need to append it */		    /* Calculate position past inserted item */		    make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);		    res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)zeros, UNFM_P_SIZE*to_paste);		    if ( res ) {			kfree(zeros);			goto error_exit_free_blocks;		    }		} else if ( is_statdata_le_ih(ih) ) {		    /* No existing item, create it */		    /* item head for new item */		    struct item_head ins_ih;		    /* create a key for our new item */		    make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3);		    /* Create new item head for our new item */		    make_le_item_head (&ins_ih, &key, key.version, 1,				       TYPE_INDIRECT, to_paste*UNFM_P_SIZE,				       0 /* free space */);		    /* Find where such item should live in the tree */		    res = search_item (inode->i_sb, &key, &path);		    if ( res != ITEM_NOT_FOUND ) {			/* item should not exist, otherwise we have error */			if ( res != -ENOSPC ) {			    reiserfs_warning (inode->i_sb,				"green-9008: search_by_key (%K) returned %d",					      &key, res);			}			res = -EIO;		        kfree(zeros);			goto error_exit_free_blocks;		    }		    res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)zeros);		} else {		    reiserfs_panic(inode->i_sb, "green-9011: Unexpected key type %K\n", &key);		}		if ( res ) {		    kfree(zeros);		    goto error_exit_free_blocks;		}		/* Now we want to check if transaction is too full, and if it is		   we restart it. This will also free the path. */		if (journal_transaction_should_end(th, th->t_blocks_allocated)) {		    res = restart_transaction(th, inode, &path);                    if (res) {                        pathrelse (&path);                        kfree(zeros);                        goto error_exit;                    }                }		/* Well, need to recalculate path and stuff */		set_cpu_key_k_offset( &key, cpu_key_k_offset(&key) + (to_paste << inode->i_blkbits));		res = search_for_position_by_key(inode->i_sb, &key, &path);		if ( res == IO_ERROR ) {		    res = -EIO;		    kfree(zeros);		    goto error_exit_free_blocks;		}		bh=get_last_bh(&path);		ih=get_ih(&path);		item = get_item(&path);		hole_size -= to_paste;	    } while ( hole_size );	    kfree(zeros);	}    }    // Go through existing indirect items first    // replace all zeroes with blocknumbers from list    // Note that if no corresponding item was found, by previous search,    // it means there are no existing in-tree representation for file area    // we are going to overwrite, so there is nothing to scan through for holes.    for ( curr_block = 0, itempos = path.pos_in_item ; curr_block < blocks_to_allocate && res == POSITION_FOUND ; ) {retry:	if ( itempos >= ih_item_len(ih)/UNFM_P_SIZE ) {	    /* We run out of data in this indirect item, let's look for another	       one. */	    /* First if we are already modifying current item, log it */	    if ( modifying_this_item ) {		journal_mark_dirty (th, inode->i_sb, bh);		modifying_this_item = 0;	    }	    /* Then set the key to look for a new indirect item (offset of old	       item is added to old item length */	    set_cpu_key_k_offset( &key, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize));	    /* Search ofor position of new key in the tree. */	    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);	    ih=get_ih(&path);	    item = get_item(&path);	    itempos = path.pos_in_item;	    continue; // loop to check all kinds of conditions and so on.	}	/* Ok, we have correct position in item now, so let's see if it is	   representing file hole (blocknumber is zero) and fill it if needed */	if ( !item[itempos] ) {	    /* Ok, a hole. Now we need to check if we already prepared this	       block to be journaled */	    while ( !modifying_this_item ) { // loop until succeed		/* Well, this item is not journaled yet, so we must prepare		   it for journal first, before we can change it */		struct item_head tmp_ih; // We copy item head of found item,					 // here to detect if fs changed under					 // us while we were preparing for					 // journal.		int fs_gen; // We store fs generation here to find if someone			    // changes fs under our feet		copy_item_head (&tmp_ih, ih); // Remember itemhead		fs_gen = get_generation (inode->i_sb); // remember fs generation		reiserfs_prepare_for_journal(inode->i_sb, bh, 1); // Prepare a buffer within which indirect item is stored for changing.		if (fs_changed (fs_gen, inode->i_sb) && item_moved (&tmp_ih, &path)) {		    // Sigh, fs was changed under us, we need to look for new		    // location of item we are working with		    /* unmark prepaerd area as journaled and search for it's		       new position */		    reiserfs_restore_prepared_buffer(inode->i_sb, bh);		    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);		    ih=get_ih(&path);		    item = get_item(&path);		    itempos = path.pos_in_item;		    goto retry;		}		modifying_this_item = 1;	    }	    item[itempos] = allocated_blocks[curr_block]; // Assign new block	    curr_block++;	}	itempos++;    }    if ( modifying_this_item ) { // We need to log last-accessed block, if it				 // was modified, but not logged yet.	journal_mark_dirty (th, inode->i_sb, bh);    }    if ( curr_block < blocks_to_allocate ) {	// Oh, well need to append to indirect item, or to create indirect item	// if there weren't any	if ( is_indirect_le_ih(ih) ) {	    // Existing indirect item - append. First calculate key for append	    // position. We do not need to recalculate path as it should	    // already point to correct place.	    make_cpu_key( &key, inode, le_key_k_offset( get_inode_item_key_version(inode), &(ih->ih_key)) + op_bytes_number(ih, inode->i_sb->s_blocksize), TYPE_INDIRECT, 3);	    res = reiserfs_paste_into_item( th, &path, &key, inode, (char *)(allocated_blocks+curr_block), UNFM_P_SIZE*(blocks_to_allocate-curr_block));	    if ( res ) {		goto error_exit_free_blocks;	    }	} else if (is_statdata_le_ih(ih) ) {	    // Last found item was statdata. That means we need to create indirect item.	    struct item_head ins_ih; /* itemhead for new item */	    /* create a key for our new item */	    make_cpu_key( &key, inode, 1, TYPE_INDIRECT, 3); // Position one,							    // because that's							    // where first							    // indirect item							    // begins	    /* Create new item head for our new item */	    make_le_item_head (&ins_ih, &key, key.version, 1, TYPE_INDIRECT,			       (blocks_to_allocate-curr_block)*UNFM_P_SIZE,			       0 /* free space */);	    /* Find where such item should live in the tree */	    res = search_item (inode->i_sb, &key, &path);	    if ( res != ITEM_NOT_FOUND ) {		/* Well, if we have found such item already, or some error		   occured, we need to warn user and return error */		if ( res != -ENOSPC ) {		    reiserfs_warning (inode->i_sb,				      "green-9009: search_by_key (%K) "				      "returned %d", &key, res);		}		res = -EIO;		goto error_exit_free_blocks;	    }	    /* Insert item into the tree with the data as its body */	    res = reiserfs_insert_item( th, &path, &key, &ins_ih, inode, (char *)(allocated_blocks+curr_block));	} else {	    reiserfs_panic(inode->i_sb, "green-9010: unexpected item type for key %K\n",&key);	}    }    // the caller is responsible for closing the transaction    // unless we return an error, they are also responsible for logging    // the inode.    //    pathrelse(&path);    /*     * cleanup prellocation from previous writes     * if this is a partial block write     */    if (write_bytes & (inode->i_sb->s_blocksize -1))        reiserfs_discard_prealloc(th, inode);    reiserfs_write_unlock(inode->i_sb);    // go through all the pages/buffers and map the buffers to newly allocated    // blocks (so that system knows where to write these pages later).    curr_block = 0;    for ( i = 0; i < num_pages ; i++ ) {	struct page *page=prepared_pages[i]; //current page	struct buffer_head *head = page_buffers(page);// first buffer for a page	int block_start, block_end; // in-page offsets for buffers.	if (!page_buffers(page))	    reiserfs_panic(inode->i_sb, "green-9005: No buffers for prepared page???");	/* For each buffer in page */	for(bh = head, block_start = 0; bh != head || !block_start;	    block_start=block_end, bh = bh->b_this_page) {	    if (!bh)		reiserfs_panic(inode->i_sb, "green-9006: Allocated but absent buffer for a page?");	    block_end = block_start+inode->i_sb->s_blocksize;	    if (i == 0 && block_end <= from )		/* if this buffer is before requested data to map, skip it */		continue;	    if (i == num_pages - 1 && block_start >= to)		/* If this buffer is after requested data to map, abort		   processing of current page */		break;	    if ( !buffer_mapped(bh) ) { // Ok, unmapped buffer, need to map it		map_bh( bh, inode->i_sb, le32_to_cpu(allocated_blocks[curr_block]));		curr_block++;		set_buffer_new(bh);	    }	}    }    RFALSE( curr_block > blocks_to_allocate, "green-9007: Used too many blocks? weird");    kfree(allocated_blocks);    return 0;// Need to deal with transaction here.error_exit_free_blocks:    pathrelse(&path);    // free blocks    for( i = 0; i < blocks_to_allocate; i++ )	reiserfs_free_block(th, inode, le32_to_cpu(allocated_blocks[i]), 1);error_exit:    if (th->t_trans_id) {        int err;        // update any changes we made to blk count        reiserfs_update_sd(th, inode);        err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS);        if (err)            res = err;    }    reiserfs_write_unlock(inode->i_sb);    kfree(allocated_blocks);    return res;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/556a2a45bce1740f035befaa7201e4ad836c7257/file.c/clean/fs/reiserfs/file.c