Esempio n. 1
0
/* add new name into a directory. If it exists in a directory - do
   nothing */
int reiserfs_add_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
			 struct key * key, int fsck_need)
{
    struct item_head entry_ih = {{0,}, };
    char * entry;
    int retval;
    INITIALIZE_PATH(path);
    int gen_counter;
    int item_len;
    __u32 hash;

    if (reiserfs_find_entry (fs, dir, name, &gen_counter))
	return 0;

    /* compose entry key to look for its place in the tree */
    entry_ih.ih_key.k_dir_id = cpu_to_le32 (dir->k_dir_id);
    entry_ih.ih_key.k_objectid = cpu_to_le32 (dir->k_objectid);
    hash = hash_value (fs, name) + gen_counter;
    if (!strcmp (name, "."))
	hash = DOT_OFFSET;
    if (!strcmp (name, ".."))
	hash = DOT_DOT_OFFSET;
    set_type_and_offset (KEY_FORMAT_1, &(entry_ih.ih_key),
			 hash, TYPE_DIRENTRY);
    set_ih_key_format (&entry_ih, KEY_FORMAT_1);
    set_entry_count (&entry_ih, 1);
    if (SB_VERSION (fs) == REISERFS_VERSION_2)
	item_len = DEH_SIZE + ROUND_UP (strlen (name));
    else
	item_len = DEH_SIZE + strlen (name);
    set_ih_item_len (&entry_ih, item_len);

    /* fsck may need to insert item which was not reached yet */
    set_ih_fsck_need( &entry_ih, fsck_need );

    entry = make_entry (0, name, key, get_offset (&(entry_ih.ih_key)));

    retval = _search_by_entry_key (fs, &(entry_ih.ih_key), &path);
    switch (retval) {
    case POSITION_NOT_FOUND:
	reiserfs_paste_into_item (fs, &path, entry, item_len);
	break;

    case DIRECTORY_NOT_FOUND:
        set_deh_location( (struct reiserfs_de_head *)entry, DEH_SIZE );
	reiserfs_insert_item (fs, &path, &entry_ih, entry);
	break;

    default:
	reiserfs_panic ("reiserfs_add_entry: looking for %k (inserting name \"%s\") "
			"search_by_entry_key returned %d",
			&(entry_ih.ih_key), name, retval);
    }

    freemem (entry);
    return item_len;
}
Esempio n. 2
0
static int reiserfs_add_entry(struct reiserfs_transaction_handle *th,
			      struct inode *dir, const char *name, int namelen,
			      struct inode *inode, int visible)
{
	struct cpu_key entry_key;
	struct reiserfs_de_head *deh;
	INITIALIZE_PATH(path);
	struct reiserfs_dir_entry de;
	DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1);
	int gen_number;
	char small_buf[32 + DEH_SIZE];	/* 48 bytes now and we avoid kmalloc
					   if we create file with short name */
	char *buffer;
	int buflen, paste_size;
	int retval;

	BUG_ON(!th->t_trans_id);

	/* cannot allow items to be added into a busy deleted directory */
	if (!namelen)
		return -EINVAL;

	if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize))
		return -ENAMETOOLONG;

	/* each entry has unique key. compose it */
	make_cpu_key(&entry_key, dir,
		     get_third_component(dir->i_sb, name, namelen),
		     TYPE_DIRENTRY, 3);

	/* get memory for composing the entry */
	buflen = DEH_SIZE + ROUND_UP(namelen);
	if (buflen > sizeof(small_buf)) {
		buffer = kmalloc(buflen, GFP_NOFS);
		if (!buffer)
			return -ENOMEM;
	} else
		buffer = small_buf;

	paste_size =
	    (get_inode_sd_version(dir) ==
	     STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen;

	/* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */
	deh = (struct reiserfs_de_head *)buffer;
	deh->deh_location = 0;	/* JDM Endian safe if 0 */
	put_deh_offset(deh, cpu_key_k_offset(&entry_key));
	deh->deh_state = 0;	/* JDM Endian safe if 0 */
	/* put key (ino analog) to de */
	deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id;	/* safe: k_dir_id is le */
	deh->deh_objectid = INODE_PKEY(inode)->k_objectid;	/* safe: k_objectid is le */

	/* copy name */
	memcpy((char *)(deh + 1), name, namelen);
	/* padd by 0s to the 4 byte boundary */
	padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen);

	/* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */
	mark_de_without_sd(deh);
	visible ? mark_de_visible(deh) : mark_de_hidden(deh);

	/* find the proper place for the new entry */
	memset(bit_string, 0, sizeof(bit_string));
	de.de_gen_number_bit_string = bit_string;
	retval = reiserfs_find_entry(dir, name, namelen, &path, &de);
	if (retval != NAME_NOT_FOUND) {
		if (buffer != small_buf)
			kfree(buffer);
		pathrelse(&path);

		if (retval == IO_ERROR) {
			return -EIO;
		}

		if (retval != NAME_FOUND) {
			reiserfs_error(dir->i_sb, "zam-7002",
				       "reiserfs_find_entry() returned "
				       "unexpected value (%d)", retval);
		}

		return -EEXIST;
	}

	gen_number =
	    find_first_zero_bit(bit_string,
				MAX_GENERATION_NUMBER + 1);
	if (gen_number > MAX_GENERATION_NUMBER) {
		/* there is no free generation number */
		reiserfs_warning(dir->i_sb, "reiserfs-7010",
				 "Congratulations! we have got hash function "
				 "screwed up");
		if (buffer != small_buf)
			kfree(buffer);
		pathrelse(&path);
		return -EBUSY;
	}
	/* adjust offset of directory enrty */
	put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number));
	set_cpu_key_k_offset(&entry_key, deh_offset(deh));

	/* update max-hash-collisions counter in reiserfs_sb_info */
	PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number);

	if (gen_number != 0) {	/* we need to re-search for the insertion point */
		if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) !=
		    NAME_NOT_FOUND) {
			reiserfs_warning(dir->i_sb, "vs-7032",
					 "entry with this key (%K) already "
					 "exists", &entry_key);

			if (buffer != small_buf)
				kfree(buffer);
			pathrelse(&path);
			return -EBUSY;
		}
	}

	/* perform the insertion of the entry that we have prepared */
	retval =
	    reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer,
				     paste_size);
	if (buffer != small_buf)
		kfree(buffer);
	if (retval) {
		reiserfs_check_path(&path);
		return retval;
	}

	dir->i_size += paste_size;
	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
	if (!S_ISDIR(inode->i_mode) && visible)
		// reiserfs_mkdir or reiserfs_rename will do that by itself
		reiserfs_update_sd(th, dir);

	reiserfs_check_path(&path);
	return 0;
}
Esempio n. 3
0
/* add entry to the directory (entry can be hidden). Does not mark dir
   inode dirty, do it after successesfull call to it */
static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, 
                               const char * name, int namelen, struct key * object_key, struct reiserfs_dir_entry * de,
			       int visible
			       )
{
  struct key entry_key;
  char * buffer;
  int buflen;
  struct reiserfs_de_head * deh;
  struct path path;
  char bit_string [MAX_GEN_NUMBER / 8 + 1];
  int gen_number;
  int repeat;
#ifdef REISERFS_ALIGNED
  int aligned_namelen = (namelen+3) & ~3;
#endif

  init_path (&path);

  if (!dir || !dir->i_sb)
    return -ENOENT;

  if ((unsigned int)namelen > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize))
    return -ENAMETOOLONG;

  /* each entry has unique key. compose it */
  copy_key (&entry_key, INODE_PKEY(dir));
  entry_key.k_offset = get_third_component (name, namelen);
  entry_key.k_uniqueness = DIRENTRY_UNIQUENESS;

  /* get memory for composing the entry */
#ifdef REISERFS_ALIGNED
  buflen = DEH_SIZE + aligned_namelen;
#else
  buflen = DEH_SIZE + namelen;
#endif
  buffer = reiserfs_kmalloc (buflen, GFP_KERNEL, dir->i_sb);
  if (buffer == 0)
    return -ENOMEM;

  /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */
  deh = (struct reiserfs_de_head *)buffer;
  deh->deh_location = 0;
  deh->deh_offset = entry_key.k_offset;
  deh->deh_state = 0;
  /* put key (ino analog) to de */
  deh->deh_dir_id = object_key->k_dir_id;
  deh->deh_objectid = object_key->k_objectid;

  /* copy name */
#ifdef REISERFS_ALIGNED
  memset( (char*)(deh+1), '\0', aligned_namelen );
#endif
  memcpy ((char *)(deh + 1), name, namelen);

  /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */
  mark_de_without_sd (deh);
  visible ? mark_de_visible (deh) : mark_de_hidden (deh);

  /* find the proper place for the new entry */
  memset (bit_string, 0, sizeof (bit_string));
  de->de_gen_number_bit_string = bit_string;
  if (reiserfs_find_entry (dir, name, namelen, &path, de) == POSITION_FOUND) {
    reiserfs_panic (dir->i_sb, "vs-7030: reiserfs_add_entry: entry with this key %k already exists",
		    &entry_key);
  }

  if (find_first_nonzero_bit (bit_string, MAX_GEN_NUMBER + 1) < MAX_GEN_NUMBER + 1) {
    /* there are few names with given hash value */
    gen_number = find_first_zero_bit (bit_string, MAX_GEN_NUMBER + 1);
    if (gen_number > MAX_GEN_NUMBER) {
      /* there is no free generation number */
      reiserfs_kfree (buffer, buflen, dir->i_sb);
      pathrelse (&path);
      return -EHASHCOLLISION;
    }
    /* adjust offset of directory enrty */
    deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, gen_number);
    entry_key.k_offset = deh->deh_offset;

    /* find place for new entry */
    if (search_by_entry_key (dir->i_sb, &entry_key, &path, &(de->de_entry_num), &repeat)) {
      reiserfs_panic (dir->i_sb, "reiserfs_add_entry: 7032: entry with this key (%k) already exists", &entry_key);
    }
  } else {
    deh->deh_offset = SET_GENERATION_NUMBER (deh->deh_offset, 0);
    entry_key.k_offset = deh->deh_offset;    
  }
  
  /* perform the insertion of the entry that we have prepared */
  if (reiserfs_paste_into_item (th, dir->i_sb, &path, &(de->de_entry_num), &entry_key, buffer, 
                                buflen, REISERFS_KERNEL_MEM, 0) == -1) {
    reiserfs_kfree (buffer, buflen, dir->i_sb);
    return -ENOSPC;
  }

  reiserfs_kfree (buffer, buflen, dir->i_sb);
  dir->i_size += buflen;
  dir->i_mtime = dir->i_ctime = CURRENT_TIME;

  return 0;
}
/* 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;
}
Esempio n. 6
0
/*
 * 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;
}