Exemple #1
0
// if root directory is empty - we set default - Yura's - hash and
// warn about it
// FIXME: we look for only one name in a directory. If tea and yura
// bith have the same value - we ask user to send report to the
// mailing list
__u32 find_hash_out (struct super_block * s)
{
    int retval;
    struct inode * inode;
    struct cpu_key key;
    INITIALIZE_PATH (path);
    struct reiserfs_dir_entry de;
    __u32 hash = DEFAULT_HASH;

    inode = s->s_root->d_inode;

    do { // Some serious "goto"-hater was there ;)
	u32 teahash, r5hash, yurahash;

	make_cpu_key (&key, inode, ~0, TYPE_DIRENTRY, 3);
	retval = search_by_entry_key (s, &key, &path, &de);
	if (retval == IO_ERROR) {
	    pathrelse (&path);
	    return UNSET_HASH ;
	}
	if (retval == NAME_NOT_FOUND)
	    de.de_entry_num --;
	set_de_name_and_namelen (&de);
	if (deh_offset( &(de.de_deh[de.de_entry_num]) ) == DOT_DOT_OFFSET) {
	    /* allow override in this case */
	    if (reiserfs_rupasov_hash(s)) {
		hash = YURA_HASH ;
	    }
	    reiserfs_warning("reiserfs: FS seems to be empty, autodetect "
	                     "is using the default hash\n");
	    break;
	}
	r5hash=GET_HASH_VALUE (r5_hash (de.de_name, de.de_namelen));
	teahash=GET_HASH_VALUE (keyed_hash (de.de_name, de.de_namelen));
	yurahash=GET_HASH_VALUE (yura_hash (de.de_name, de.de_namelen));
	if ( ( (teahash == r5hash) && (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash) ) ||
	     ( (teahash == yurahash) && (yurahash == GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])))) ) ||
	     ( (r5hash == yurahash) && (yurahash == GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])))) ) ) {
	    reiserfs_warning("reiserfs: Unable to automatically detect hash"
		"function for device %s\n"
		"please mount with -o hash={tea,rupasov,r5}\n", kdevname (s->s_dev));
	    hash = UNSET_HASH;
	    break;
	}
	if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == yurahash)
	    hash = YURA_HASH;
	else if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == teahash)
	    hash = TEA_HASH;
	else if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) == r5hash)
	    hash = R5_HASH;
	else {
	    reiserfs_warning("reiserfs: Unrecognised hash function for "
			     "device %s\n", kdevname (s->s_dev));
	    hash = UNSET_HASH;
	}
    } while (0);

    pathrelse (&path);
    return hash;
}
Exemple #2
0
int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct dentry * dentry)
{
  struct inode *inode = old_dentry->d_inode;
  struct path path_to_entry;
  struct reiserfs_dir_entry de;
  int error;
  int windex ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
  
  init_path (&path_to_entry);

  /* object must not be directory */
  if (S_ISDIR(inode->i_mode)) {
    return -EPERM;
  }
  
  /* file has too many links */
  if (inode->i_nlink >= REISERFS_LINK_MAX) {
    return -EMLINK;
  }

  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiserfs_link") ;

  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) {
    pathrelse (&path_to_entry);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    return -EEXIST;
  }
  
  pathrelse (&path_to_entry);

  /* free preserve list if we should */
/*  maybe_free_preserve_list (dir->i_sb);*/

  /* create new entry */
  error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1);
  if (error) {
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    return error;
  }
  inode->i_nlink++;
  inode->i_ctime = CURRENT_TIME;
  if_in_ram_update_sd (&th, inode);
  if_in_ram_update_sd (&th, dir);
  inode->i_count++;
  d_instantiate(dentry, inode);
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  return 0;
}
Exemple #3
0
/* The function is NOT SCHEDULE-SAFE! */
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
			struct treepath *path, struct reiserfs_dir_entry *de)
{
	int retval;

	retval = search_item(sb, key, path);
	switch (retval) {
	case ITEM_NOT_FOUND:
		if (!PATH_LAST_POSITION(path)) {
			reiserfs_error(sb, "vs-7000", "search_by_key "
				       "returned item position == 0");
			pathrelse(path);
			return IO_ERROR;
		}
		PATH_LAST_POSITION(path)--;

	case ITEM_FOUND:
		break;

	case IO_ERROR:
		return retval;

	default:
		pathrelse(path);
		reiserfs_error(sb, "vs-7002", "no path to here");
		return IO_ERROR;
	}

	set_de_item_location(de, path);

#ifdef CONFIG_REISERFS_CHECK
	if (!is_direntry_le_ih(de->de_ih) ||
	    COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) {
		print_block(de->de_bh, 0, -1, -1);
		reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
			       "item or does not belong to the same directory "
			       "as key %K", de->de_ih, key);
	}
#endif				/* CONFIG_REISERFS_CHECK */

	/*
	 * binary search in directory item by third component of the
	 * key. sets de->de_entry_num of de
	 */
	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
	path->pos_in_item = de->de_entry_num;
	if (retval != NAME_NOT_FOUND) {
		/*
		 * ugly, but rename needs de_bh, de_deh, de_name,
		 * de_namelen, de_objectid set
		 */
		set_de_name_and_namelen(de);
		set_de_object_key(de);
	}
	return retval;
}
/*
 * We assign a key to each directory item, and place multiple entries in
 * a single directory item. A directory item has a key equal to the key
 * of the first directory entry in it.
 *
 * This function first calls search_by_key, then, if item whose first
 * entry matches is not found it looks for the entry inside directory
 * item found by search_by_key. Fills the path to the entry, and to the
 * entry position in the item
 */
int
search_by_entry_key(struct reiserfs_sb_info *sbi,
    const struct cpu_key *key, struct path *path,
    struct reiserfs_dir_entry *de)
{
	int retval;

	reiserfs_log(LOG_DEBUG, "searching in (objectid=%d,dirid=%d)\n",
	    key->on_disk_key.k_objectid, key->on_disk_key.k_dir_id);
	retval = search_item(sbi, key, path);
	switch (retval) {
	case ITEM_NOT_FOUND:
		if (!PATH_LAST_POSITION(path)) {
			reiserfs_log(LOG_DEBUG,
			    "search_by_key returned item position == 0");
			pathrelse(path);
			return (IO_ERROR);
		}
		PATH_LAST_POSITION(path)--;
		reiserfs_log(LOG_DEBUG, "search_by_key did not found it\n");
		break;
	case ITEM_FOUND:
		reiserfs_log(LOG_DEBUG, "search_by_key found it\n");
		break;
	case IO_ERROR:
		return (retval);
	default:
		pathrelse(path);
		reiserfs_log(LOG_DEBUG, "no path to here");
		return (IO_ERROR);
	}

	reiserfs_log(LOG_DEBUG, "set item location\n");
	set_de_item_location(de, path);

	/*
	 * Binary search in directory item by third component of the
	 * key. Sets de->de_entry_num of de
	 */
	reiserfs_log(LOG_DEBUG, "bin_search_in_dir_item\n");
	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
	path->pos_in_item = de->de_entry_num;
	if (retval != NAME_NOT_FOUND) {
		/*
		 * Ugly, but rename needs de_bp, de_deh, de_name, de_namelen,
		 * de_objectid set
		 */
		set_de_name_and_namelen(de);
		set_de_object_key(de);
		reiserfs_log(LOG_DEBUG, "set (objectid=%d,dirid=%d)\n",
		    de->de_objectid, de->de_dir_id);
	}

	return (retval);
}
Exemple #5
0
// if root directory is empty - we set default - Yura's - hash and
// warn about it
// FIXME: we look for only one name in a directory. If tea and yura
// bith have the same value - we ask user to send report to the
// mailing list
__u32 find_hash_out (struct super_block * s)
{
    int retval;
    struct inode * inode;
    struct cpu_key key;
    INITIALIZE_PATH (path);
    struct reiserfs_dir_entry de;
    __u32 hash = DEFAULT_HASH;

    inode = s->s_root->d_inode;

    while (1) {
	make_cpu_key (&key, inode, ~0, TYPE_DIRENTRY, 3);
	retval = search_by_entry_key (s, &key, &path, &de);
	if (retval == IO_ERROR) {
	    pathrelse (&path);
	    return UNSET_HASH ;
	}
	if (retval == NAME_NOT_FOUND)
	    de.de_entry_num --;
	set_de_name_and_namelen (&de);
	if (deh_offset( &(de.de_deh[de.de_entry_num]) ) == DOT_DOT_OFFSET) {
	    /* allow override in this case */
	    if (reiserfs_rupasov_hash(s)) {
		hash = YURA_HASH ;
	    }
	    reiserfs_warning("reiserfs: FS seems to be empty, autodetect "
	                     "is using the default hash\n");
	    break;
	}
	if (GET_HASH_VALUE(yura_hash (de.de_name, de.de_namelen)) == 
	    GET_HASH_VALUE(keyed_hash (de.de_name, de.de_namelen))) {
	    reiserfs_warning ("reiserfs: Could not detect hash function "
			      "please mount with -o hash={tea,rupasov,r5}\n") ;
	    hash = UNSET_HASH ;
	    break;
	}
	if (GET_HASH_VALUE( deh_offset(&(de.de_deh[de.de_entry_num])) ) ==
	    GET_HASH_VALUE (yura_hash (de.de_name, de.de_namelen)))
	    hash = YURA_HASH;
	else
	    hash = TEA_HASH;
	break;
    }

    pathrelse (&path);
    return hash;
}
/*
** looks up the dentry of the parent directory for child.
** taken from ext2_get_parent
*/
struct dentry *reiserfs_get_parent(struct dentry *child)
{
	int retval;
	struct inode *inode = NULL;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);
	struct inode *dir = child->d_inode;

	if (dir->i_nlink == 0) {
		return ERR_PTR(-ENOENT);
	}
	de.de_gen_number_bit_string = NULL;

	reiserfs_write_lock(dir->i_sb);
	retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de);
	pathrelse(&path_to_entry);
	if (retval != NAME_FOUND) {
		reiserfs_write_unlock(dir->i_sb);
		return ERR_PTR(-ENOENT);
	}
	inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
	reiserfs_write_unlock(dir->i_sb);

	return d_obtain_alias(inode);
}
Exemple #7
0
/* 
** looks up the dentry of the parent directory for child.
** taken from ext2_get_parent
*/
struct dentry *reiserfs_get_parent(struct dentry *child)
{
    int retval;
    struct inode * inode = NULL;
    struct reiserfs_dir_entry de;
    INITIALIZE_PATH (path_to_entry);
    struct dentry *parent;
    struct inode *dir = child->d_inode ;


    if (dir->i_nlink == 0) {
	return ERR_PTR(-ENOENT);
    }
    de.de_gen_number_bit_string = NULL;

    reiserfs_write_lock(dir->i_sb);
    retval = reiserfs_find_entry (dir, "..", 2, &path_to_entry, &de);
    pathrelse (&path_to_entry);
    if (retval != NAME_FOUND) {
	reiserfs_write_unlock(dir->i_sb);
	return ERR_PTR(-ENOENT);
    }
    inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
    reiserfs_write_unlock(dir->i_sb);

    if (!inode || IS_ERR(inode)) {
	return ERR_PTR(-EACCES);
    }
    parent = d_alloc_anon(inode);
    if (!parent) {
	iput(inode);
	parent = ERR_PTR(-ENOMEM);
    }
    return parent;
}
int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key)
{
    struct path path;
    struct tree_balance tb;
    struct item_head * ih;
    struct reiserfs_de_head * deh;

    if (_search_by_entry_key (fs, key, &path) != POSITION_FOUND) {
	pathrelse (&path);
	return 1;
    }

    ih = get_ih (&path);
    if (ih_entry_count (ih) == 1) {
	_init_tb_struct (&tb, fs, &path, -(IH_SIZE + ih_item_len (ih)));
	if (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON) {
	    unfix_nodes (&tb);
	    return 1;
	}
	do_balance (&tb, 0, 0, M_DELETE, 0);
	return 0;
    }

    deh = B_I_DEH (get_bh (&path), ih) + path.pos_in_item;
    _init_tb_struct (&tb, fs, &path, -(DEH_SIZE + entry_length (ih, deh, path.pos_in_item)));
    if (fix_nodes (M_CUT, &tb, 0) != CARRY_ON) {
	unfix_nodes (&tb);
	return 1;
    }
    do_balance (&tb, 0, 0, M_CUT, 0);
    return 0;
}
static int _search_by_key (reiserfs_filsys_t fs, struct key * key, struct path * path)
{
    struct buffer_head * bh;
    unsigned long block = SB_ROOT_BLOCK (fs);
    struct path_element * curr;
    int retval;
    
    path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
    while (1) {
	curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length);
	bh = curr->pe_buffer = bread (fs->s_dev, block, fs->s_blocksize);
        if (bh == 0) {
	    path->path_length --;
	    pathrelse (path);
	    return ITEM_NOT_FOUND;
	}
	retval = _bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh),
			      is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), comp_keys);
	if (retval == ITEM_FOUND) {
	    /* key found, return if this is leaf level */
	    if (is_leaf_node (bh)) {
		path->pos_in_item = 0;
		return ITEM_FOUND;
	    }
	    curr->pe_position ++;
	} else {
	    /* key not found in the node */
	    if (is_leaf_node (bh))
		return ITEM_NOT_FOUND;
	}
	block = B_N_CHILD_NUM (bh, curr->pe_position);
    }
    printf ("search_by_key: you can not get here\n");
    return ITEM_NOT_FOUND;
}
Exemple #10
0
static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, struct path * path_to_entry, struct reiserfs_dir_entry * de)
{
  struct key key_to_search;
  int repeat;
  int retval;

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

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

  /* there are no entries having the same third component of key, so
     fourth key component is not used */
  copy_key (&key_to_search, INODE_PKEY (dir));
  key_to_search.k_offset = get_third_component (name, namelen);
  key_to_search.k_uniqueness = DIRENTRY_UNIQUENESS;

  while (1) {
    /* search for a directory item using the formed key */
    if (search_by_key (dir->i_sb, &key_to_search, path_to_entry, &repeat, DISK_LEAF_NODE_LEVEL, READ_BLOCKS) == ITEM_NOT_FOUND) {
      /* take previous item */
#ifdef REISERFS_CHECK
      if (!PATH_LAST_POSITION (path_to_entry))
	reiserfs_panic (dir->i_sb, "vs-7010: reiserfs_find_entry: search_by_key returned bad position == 0");
#endif /* REISERFS_CHECK */
      PATH_LAST_POSITION (path_to_entry) --;
    }
    
    de->de_bh = PATH_PLAST_BUFFER (path_to_entry);
    de->de_item_num = PATH_LAST_POSITION (path_to_entry);
    de->de_ih = B_N_PITEM_HEAD (de->de_bh, de->de_item_num);
    de->de_deh = B_I_DEH (de->de_bh, de->de_ih);

#ifdef REISERFS_CHECK
    if (!I_IS_DIRECTORY_ITEM (de->de_ih) || COMP_SHORT_KEYS (&(de->de_ih->ih_key), INODE_PKEY (dir)))
      reiserfs_panic (dir->i_sb, "vs-7020: reiserfs_find_entry: item must be an item of the same directory item as inode");
#endif /* REISERFS_CHECK */

    /* we do not check whether bin_search_in_dir_item found the given key, even if so, we still have
       to compare names */
    bin_search_in_dir_item (de->de_ih, de->de_deh, &key_to_search, &(de->de_entry_num));

    /* compare names for all entries having given hash value */
    retval = linear_search_in_dir_item (&key_to_search, de, name, namelen);
    if (retval != GOTO_PREVIOUS_ITEM)
      /* there is no need to scan directory anymore. Given entry found or does not exist */
      return retval;

    /* there is left neighboring item of this directory and given entry can be there */
    key_to_search.k_offset = de->de_ih->ih_key.k_offset - 1;
    pathrelse (path_to_entry);

  } /* while (1) */
}
/*
 * May return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
 * FIXME: should add something like IOERROR
 */
static int
reiserfs_find_entry(struct reiserfs_node *dp, const char *name, int namelen,
    struct path * path_to_entry, struct reiserfs_dir_entry *de)
{
	struct cpu_key key_to_search;
	int retval;

	if (namelen > REISERFS_MAX_NAME(dp->i_reiserfs->s_blocksize))
		return NAME_NOT_FOUND;

	/* We will search for this key in the tree */
	make_cpu_key(&key_to_search, dp,
	    get_third_component(dp->i_reiserfs, name, namelen),
	    TYPE_DIRENTRY, 3);

	while (1) {
		reiserfs_log(LOG_DEBUG, "search by entry key\n");
		retval = search_by_entry_key(dp->i_reiserfs, &key_to_search,
		    path_to_entry, de);
		if (retval == IO_ERROR) {
			reiserfs_log(LOG_DEBUG, "IO error in %s\n",
			    __FUNCTION__);
			return IO_ERROR;
		}

		/* Compare names for all entries having given hash value */
		reiserfs_log(LOG_DEBUG, "linear search for `%s'\n", name);
		retval = linear_search_in_dir_item(&key_to_search, de,
		    name, namelen);
		if (retval != GOTO_PREVIOUS_ITEM) {
			/*
			 * There is no need to scan directory anymore.
			 * Given entry found or does not exist
			 */
			reiserfs_log(LOG_DEBUG, "linear search returned "
			    "(objectid=%d,dirid=%d)\n",
			    de->de_objectid, de->de_dir_id);
			path_to_entry->pos_in_item = de->de_entry_num;
			return retval;
		}

		/*
		 * There is left neighboring item of this directory and
		 * given entry can be there
		 */
		set_cpu_key_k_offset(&key_to_search,
		    le_ih_k_offset(de->de_ih) - 1);
		pathrelse(path_to_entry);  
	} /* while (1) */
}
Exemple #12
0
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
				      struct nameidata *nd)
{
	int retval;
	struct inode *inode = NULL;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);

	if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
		return ERR_PTR(-ENAMETOOLONG);

	reiserfs_write_lock(dir->i_sb);
	de.de_gen_number_bit_string = NULL;
	retval =
	    reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
				&path_to_entry, &de);
	pathrelse(&path_to_entry);
	if (retval == NAME_FOUND) {
		/* Hide the .reiserfs_priv directory */
		if (reiserfs_xattrs(dir->i_sb) &&
		    !old_format_only(dir->i_sb) &&
		    REISERFS_SB(dir->i_sb)->priv_root &&
		    REISERFS_SB(dir->i_sb)->priv_root->d_inode &&
		    de.de_objectid ==
		    le32_to_cpu(INODE_PKEY
				(REISERFS_SB(dir->i_sb)->priv_root->d_inode)->
				k_objectid)) {
			reiserfs_write_unlock(dir->i_sb);
			return ERR_PTR(-EACCES);
		}

		inode =
		    reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id));
		if (!inode || IS_ERR(inode)) {
			reiserfs_write_unlock(dir->i_sb);
			return ERR_PTR(-EACCES);
		}

		/* Propogate the priv_object flag so we know we're in the priv tree */
		if (is_reiserfs_priv_object(dir))
			reiserfs_mark_inode_private(inode);
	}
	reiserfs_write_unlock(dir->i_sb);
	if (retval == IO_ERROR) {
		return ERR_PTR(-EIO);
	}

	return d_splice_alias(inode, dentry);
}
Exemple #13
0
/*
 * may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND
 * FIXME: should add something like IOERROR
 */
static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
			       struct treepath *path_to_entry,
			       struct reiserfs_dir_entry *de)
{
	struct cpu_key key_to_search;
	int retval;

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

	/* we will search for this key in the tree */
	make_cpu_key(&key_to_search, dir,
		     get_third_component(dir->i_sb, name, namelen),
		     TYPE_DIRENTRY, 3);

	while (1) {
		retval =
		    search_by_entry_key(dir->i_sb, &key_to_search,
					path_to_entry, de);
		if (retval == IO_ERROR) {
			reiserfs_error(dir->i_sb, "zam-7001", "io error");
			return IO_ERROR;
		}

		/* compare names for all entries having given hash value */
		retval =
		    linear_search_in_dir_item(&key_to_search, de, name,
					      namelen);
		/*
		 * there is no need to scan directory anymore.
		 * Given entry found or does not exist
		 */
		if (retval != GOTO_PREVIOUS_ITEM) {
			path_to_entry->pos_in_item = de->de_entry_num;
			return retval;
		}

		/*
		 * there is left neighboring item of this directory
		 * and given entry can be there
		 */
		set_cpu_key_k_offset(&key_to_search,
				     le_ih_k_offset(de->de_ih) - 1);
		pathrelse(path_to_entry);

	}			/* while (1) */
}
Exemple #14
0
/* Decrement b_count field of the all buffers in the path. */
void
decrement_counters_in_path(struct path *p_s_search_path)
{

	pathrelse(p_s_search_path);
#if 0
	int n_path_offset = p_s_search_path->path_length;

	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
		struct buf *bp;

		bp = PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--);
		decrement_bcount(bp);
	}

	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
#endif
}
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
				      struct nameidata *nd)
{
	int retval;
	int lock_depth;
	struct inode *inode = NULL;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);

	if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
		return ERR_PTR(-ENAMETOOLONG);

	/*
	 * Might be called with or without the write lock, must be careful
	 * to not recursively hold it in case we want to release the lock
	 * before rescheduling.
	 */
	lock_depth = reiserfs_write_lock_once(dir->i_sb);

	de.de_gen_number_bit_string = NULL;
	retval =
	    reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
				&path_to_entry, &de);
	pathrelse(&path_to_entry);
	if (retval == NAME_FOUND) {
		inode = reiserfs_iget(dir->i_sb,
				      (struct cpu_key *)&(de.de_dir_id));
		if (!inode || IS_ERR(inode)) {
			reiserfs_write_unlock_once(dir->i_sb, lock_depth);
			return ERR_PTR(-EACCES);
		}

		/* Propagate the private flag so we know we're
		 * in the priv tree */
		if (IS_PRIVATE(dir))
			inode->i_flags |= S_PRIVATE;
	}
	reiserfs_write_unlock_once(dir->i_sb, lock_depth);
	if (retval == IO_ERROR) {
		return ERR_PTR(-EIO);
	}

	return d_splice_alias(inode, dentry);
}
Exemple #16
0
struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry)
{
  struct inode * inode = 0;
  struct reiserfs_dir_entry de;
  struct path path_to_entry;
  int error;

  init_path (&path_to_entry);

  de.de_gen_number_bit_string = 0;
  error = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de);
  pathrelse (&path_to_entry);
  if (error == POSITION_FOUND) {
    inode = reiserfs_iget (dir->i_sb, (struct key *)&(de.de_dir_id));
    if (!inode)
      return ERR_PTR(-EACCES);
  }

  d_add(dentry, inode);
  return NULL;
}
Exemple #17
0
static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
				      unsigned int flags)
{
	int retval;
	struct inode *inode = NULL;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);

	if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
		return ERR_PTR(-ENAMETOOLONG);

	reiserfs_write_lock(dir->i_sb);

	de.de_gen_number_bit_string = NULL;
	retval =
	    reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
				&path_to_entry, &de);
	pathrelse(&path_to_entry);
	if (retval == NAME_FOUND) {
		inode = reiserfs_iget(dir->i_sb,
				      (struct cpu_key *)&de.de_dir_id);
		if (!inode || IS_ERR(inode)) {
			reiserfs_write_unlock(dir->i_sb);
			return ERR_PTR(-EACCES);
		}

		/*
		 * Propagate the private flag so we know we're
		 * in the priv tree
		 */
		if (IS_PRIVATE(dir))
			inode->i_flags |= S_PRIVATE;
	}
	reiserfs_write_unlock(dir->i_sb);
	if (retval == IO_ERROR) {
		return ERR_PTR(-EIO);
	}

	return d_splice_alias(inode, dentry);
}
Exemple #18
0
int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
{
  int retval;
  struct inode * inode;
  struct reiserfs_dir_entry de;
  struct path path;
  int windex ;
  int call_journal_end = 1 ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 

  init_path (&path);

  retval = -ENOENT;
	
  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiserfs_unlink") ;
  /* free preserve list if we should */
/*  maybe_free_preserve_list (dir->i_sb);*/
	
  de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de) == POSITION_NOT_FOUND) {
    goto end_unlink;
  }

  inode = dentry->d_inode;

  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  retval = -EPERM;
  if (S_ISDIR (inode->i_mode)) {
    goto end_unlink;
  }
  if ((dir->i_mode & S_ISVTX) && !fsuser() &&
      current->fsuid != inode->i_uid &&
      current->fsuid != dir->i_uid) {
    goto end_unlink;
  }

  retval = -ENOENT;
  if (comp_short_keys ((struct key *)&(de.de_dir_id), INODE_PKEY (inode))) {
    goto end_unlink;
  }
  
  if (!inode->i_nlink) {
    printk("reiserfs_unlink: deleting nonexistent file (%s:%lu), %d\n",
	   kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
    inode->i_nlink = 1;
  }
  if (reiserfs_cut_from_item (&th, dir, dir->i_sb, &path, &(de.de_entry_num), &(de.de_entry_key), 0, NOTHING_SPECIAL) == 0) {
    retval = -ENOENT;
    goto end_unlink;
  }

  inode->i_nlink--;
  inode->i_ctime = CURRENT_TIME;
  if_in_ram_update_sd (&th, inode);

  dir->i_size -= (de.de_entrylen + DEH_SIZE);
  dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  if_in_ram_update_sd (&th, dir) ;
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  call_journal_end = 0 ;
  d_delete(dentry); 
  retval = 0;

end_unlink:
  pathrelse (&path);
  pop_journal_writer(windex) ;
  if (call_journal_end) 
    journal_end(&th, dir->i_sb, jbegin_count) ;
  return retval;
}
static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
{
	int retval, err;
	struct inode *inode;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path);
	struct reiserfs_transaction_handle th;
	int jbegin_count;
	unsigned long savelink;
	int depth;

	dquot_initialize(dir);

	inode = dentry->d_inode;

	/* in this transaction we can be doing at max two balancings and update
	 * two stat datas, we change quotas of the owner of the directory and of
	 * the owner of the parent directory. The quota structure is possibly
	 * deleted only on iput => outside of this transaction */
	jbegin_count =
	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);

	depth = reiserfs_write_lock_once(dir->i_sb);
	retval = journal_begin(&th, dir->i_sb, jbegin_count);
	if (retval)
		goto out_unlink;

	de.de_gen_number_bit_string = NULL;
	if ((retval =
	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
				 &path, &de)) == NAME_NOT_FOUND) {
		retval = -ENOENT;
		goto end_unlink;
	} else if (retval == IO_ERROR) {
		retval = -EIO;
		goto end_unlink;
	}

	reiserfs_update_inode_transaction(inode);
	reiserfs_update_inode_transaction(dir);

	if (de.de_objectid != inode->i_ino) {
		// FIXME: compare key of an object and a key found in the
		// entry
		retval = -EIO;
		goto end_unlink;
	}

	if (!inode->i_nlink) {
		reiserfs_warning(inode->i_sb, "reiserfs-7042",
				 "deleting nonexistent file (%lu), %d",
				 inode->i_ino, inode->i_nlink);
		set_nlink(inode, 1);
	}

	drop_nlink(inode);

	/*
	 * we schedule before doing the add_save_link call, save the link
	 * count so we don't race
	 */
	savelink = inode->i_nlink;

	retval =
	    reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL,
				   0);
	if (retval < 0) {
		inc_nlink(inode);
		goto end_unlink;
	}
	inode->i_ctime = CURRENT_TIME_SEC;
	reiserfs_update_sd(&th, inode);

	dir->i_size -= (de.de_entrylen + DEH_SIZE);
	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
	reiserfs_update_sd(&th, dir);

	if (!savelink)
		/* prevent file from getting lost */
		add_save_link(&th, inode, 0 /* not truncate */ );

	retval = journal_end(&th, dir->i_sb, jbegin_count);
	reiserfs_check_path(&path);
	reiserfs_write_unlock_once(dir->i_sb, depth);
	return retval;

      end_unlink:
	pathrelse(&path);
	err = journal_end(&th, dir->i_sb, jbegin_count);
	reiserfs_check_path(&path);
	if (err)
		retval = err;
      out_unlink:
	reiserfs_write_unlock_once(dir->i_sb, depth);
	return retval;
}
static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
{
	int retval, err;
	struct inode *inode;
	struct reiserfs_transaction_handle th;
	int jbegin_count;
	INITIALIZE_PATH(path);
	struct reiserfs_dir_entry de;

	/* we will be doing 2 balancings and update 2 stat data, we change quotas
	 * of the owner of the directory and of the owner of the parent directory.
	 * The quota structure is possibly deleted only on last iput => outside
	 * of this transaction */
	jbegin_count =
	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);

	dquot_initialize(dir);

	reiserfs_write_lock(dir->i_sb);
	retval = journal_begin(&th, dir->i_sb, jbegin_count);
	if (retval)
		goto out_rmdir;

	de.de_gen_number_bit_string = NULL;
	if ((retval =
	     reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len,
				 &path, &de)) == NAME_NOT_FOUND) {
		retval = -ENOENT;
		goto end_rmdir;
	} else if (retval == IO_ERROR) {
		retval = -EIO;
		goto end_rmdir;
	}

	inode = dentry->d_inode;

	reiserfs_update_inode_transaction(inode);
	reiserfs_update_inode_transaction(dir);

	if (de.de_objectid != inode->i_ino) {
		// FIXME: compare key of an object and a key found in the
		// entry
		retval = -EIO;
		goto end_rmdir;
	}
	if (!reiserfs_empty_dir(inode)) {
		retval = -ENOTEMPTY;
		goto end_rmdir;
	}

	/* cut entry from dir directory */
	retval = reiserfs_cut_from_item(&th, &path, &(de.de_entry_key), dir, NULL,	/* page */
					0 /*new file size - not used here */ );
	if (retval < 0)
		goto end_rmdir;

	if (inode->i_nlink != 2 && inode->i_nlink != 1)
		reiserfs_error(inode->i_sb, "reiserfs-7040",
			       "empty directory has nlink != 2 (%d)",
			       inode->i_nlink);

	clear_nlink(inode);
	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
	reiserfs_update_sd(&th, inode);

	DEC_DIR_INODE_NLINK(dir)
	    dir->i_size -= (DEH_SIZE + de.de_entrylen);
	reiserfs_update_sd(&th, dir);

	/* prevent empty directory from getting lost */
	add_save_link(&th, inode, 0 /* not truncate */ );

	retval = journal_end(&th, dir->i_sb, jbegin_count);
	reiserfs_check_path(&path);
      out_rmdir:
	reiserfs_write_unlock(dir->i_sb);
	return retval;

      end_rmdir:
	/* we must release path, because we did not call
	   reiserfs_cut_from_item, or reiserfs_cut_from_item does not
	   release path if operation was not complete */
	pathrelse(&path);
	err = journal_end(&th, dir->i_sb, jbegin_count);
	reiserfs_write_unlock(dir->i_sb);
	return err ? err : retval;
}
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;
}
Exemple #22
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;
}
/*
 * process, that is going to call fix_nodes/do_balance must hold only
 * one path. If it holds 2 or more, it can get into endless waiting in
 * get_empty_nodes or its clones
 */
static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			   struct inode *new_dir, struct dentry *new_dentry)
{
	int retval;
	INITIALIZE_PATH(old_entry_path);
	INITIALIZE_PATH(new_entry_path);
	INITIALIZE_PATH(dot_dot_entry_path);
	struct item_head new_entry_ih, old_entry_ih, dot_dot_ih;
	struct reiserfs_dir_entry old_de, new_de, dot_dot_de;
	struct inode *old_inode, *new_dentry_inode;
	struct reiserfs_transaction_handle th;
	int jbegin_count;
	umode_t old_inode_mode;
	unsigned long savelink = 1;
	struct timespec ctime;

	/* three balancings: (1) old name removal, (2) new name insertion
	   and (3) maybe "save" link insertion
	   stat data updates: (1) old directory,
	   (2) new directory and (3) maybe old object stat data (when it is
	   directory) and (4) maybe stat data of object to which new entry
	   pointed initially and (5) maybe block containing ".." of
	   renamed directory
	   quota updates: two parent directories */
	jbegin_count =
	    JOURNAL_PER_BALANCE_CNT * 3 + 5 +
	    4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);

	dquot_initialize(old_dir);
	dquot_initialize(new_dir);

	old_inode = old_dentry->d_inode;
	new_dentry_inode = new_dentry->d_inode;

	// make sure, that oldname still exists and points to an object we
	// are going to rename
	old_de.de_gen_number_bit_string = NULL;
	reiserfs_write_lock(old_dir->i_sb);
	retval =
	    reiserfs_find_entry(old_dir, old_dentry->d_name.name,
				old_dentry->d_name.len, &old_entry_path,
				&old_de);
	pathrelse(&old_entry_path);
	if (retval == IO_ERROR) {
		reiserfs_write_unlock(old_dir->i_sb);
		return -EIO;
	}

	if (retval != NAME_FOUND || old_de.de_objectid != old_inode->i_ino) {
		reiserfs_write_unlock(old_dir->i_sb);
		return -ENOENT;
	}

	old_inode_mode = old_inode->i_mode;
	if (S_ISDIR(old_inode_mode)) {
		// make sure, that directory being renamed has correct ".."
		// and that its new parent directory has not too many links
		// already

		if (new_dentry_inode) {
			if (!reiserfs_empty_dir(new_dentry_inode)) {
				reiserfs_write_unlock(old_dir->i_sb);
				return -ENOTEMPTY;
			}
		}

		/* directory is renamed, its parent directory will be changed,
		 ** so find ".." entry
		 */
		dot_dot_de.de_gen_number_bit_string = NULL;
		retval =
		    reiserfs_find_entry(old_inode, "..", 2, &dot_dot_entry_path,
					&dot_dot_de);
		pathrelse(&dot_dot_entry_path);
		if (retval != NAME_FOUND) {
			reiserfs_write_unlock(old_dir->i_sb);
			return -EIO;
		}

		/* inode number of .. must equal old_dir->i_ino */
		if (dot_dot_de.de_objectid != old_dir->i_ino) {
			reiserfs_write_unlock(old_dir->i_sb);
			return -EIO;
		}
	}

	retval = journal_begin(&th, old_dir->i_sb, jbegin_count);
	if (retval) {
		reiserfs_write_unlock(old_dir->i_sb);
		return retval;
	}

	/* add new entry (or find the existing one) */
	retval =
	    reiserfs_add_entry(&th, new_dir, new_dentry->d_name.name,
			       new_dentry->d_name.len, old_inode, 0);
	if (retval == -EEXIST) {
		if (!new_dentry_inode) {
			reiserfs_panic(old_dir->i_sb, "vs-7050",
				       "new entry is found, new inode == 0");
		}
	} else if (retval) {
		int err = journal_end(&th, old_dir->i_sb, jbegin_count);
		reiserfs_write_unlock(old_dir->i_sb);
		return err ? err : retval;
	}

	reiserfs_update_inode_transaction(old_dir);
	reiserfs_update_inode_transaction(new_dir);

	/* this makes it so an fsync on an open fd for the old name will
	 ** commit the rename operation
	 */
	reiserfs_update_inode_transaction(old_inode);

	if (new_dentry_inode)
		reiserfs_update_inode_transaction(new_dentry_inode);

	while (1) {
		// look for old name using corresponding entry key (found by reiserfs_find_entry)
		if ((retval =
		     search_by_entry_key(new_dir->i_sb, &old_de.de_entry_key,
					 &old_entry_path,
					 &old_de)) != NAME_FOUND) {
			pathrelse(&old_entry_path);
			journal_end(&th, old_dir->i_sb, jbegin_count);
			reiserfs_write_unlock(old_dir->i_sb);
			return -EIO;
		}

		copy_item_head(&old_entry_ih, get_ih(&old_entry_path));

		reiserfs_prepare_for_journal(old_inode->i_sb, old_de.de_bh, 1);

		// look for new name by reiserfs_find_entry
		new_de.de_gen_number_bit_string = NULL;
		retval =
		    reiserfs_find_entry(new_dir, new_dentry->d_name.name,
					new_dentry->d_name.len, &new_entry_path,
					&new_de);
		// reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from
		// reiserfs_add_entry above, and we'll catch any i/o errors before we get here.
		if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
			pathrelse(&new_entry_path);
			pathrelse(&old_entry_path);
			journal_end(&th, old_dir->i_sb, jbegin_count);
			reiserfs_write_unlock(old_dir->i_sb);
			return -EIO;
		}

		copy_item_head(&new_entry_ih, get_ih(&new_entry_path));

		reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1);

		if (S_ISDIR(old_inode->i_mode)) {
			if ((retval =
			     search_by_entry_key(new_dir->i_sb,
						 &dot_dot_de.de_entry_key,
						 &dot_dot_entry_path,
						 &dot_dot_de)) != NAME_FOUND) {
				pathrelse(&dot_dot_entry_path);
				pathrelse(&new_entry_path);
				pathrelse(&old_entry_path);
				journal_end(&th, old_dir->i_sb, jbegin_count);
				reiserfs_write_unlock(old_dir->i_sb);
				return -EIO;
			}
			copy_item_head(&dot_dot_ih,
				       get_ih(&dot_dot_entry_path));
			// node containing ".." gets into transaction
			reiserfs_prepare_for_journal(old_inode->i_sb,
						     dot_dot_de.de_bh, 1);
		}
		/* we should check seals here, not do
		   this stuff, yes? Then, having
		   gathered everything into RAM we
		   should lock the buffers, yes?  -Hans */
		/* probably.  our rename needs to hold more
		 ** than one path at once.  The seals would
		 ** have to be written to deal with multi-path
		 ** issues -chris
		 */
		/* sanity checking before doing the rename - avoid races many
		 ** of the above checks could have scheduled.  We have to be
		 ** sure our items haven't been shifted by another process.
		 */
		if (item_moved(&new_entry_ih, &new_entry_path) ||
		    !entry_points_to_object(new_dentry->d_name.name,
					    new_dentry->d_name.len,
					    &new_de, new_dentry_inode) ||
		    item_moved(&old_entry_ih, &old_entry_path) ||
		    !entry_points_to_object(old_dentry->d_name.name,
					    old_dentry->d_name.len,
					    &old_de, old_inode)) {
			reiserfs_restore_prepared_buffer(old_inode->i_sb,
							 new_de.de_bh);
			reiserfs_restore_prepared_buffer(old_inode->i_sb,
							 old_de.de_bh);
			if (S_ISDIR(old_inode_mode))
				reiserfs_restore_prepared_buffer(old_inode->
								 i_sb,
								 dot_dot_de.
								 de_bh);
			continue;
		}
		if (S_ISDIR(old_inode_mode)) {
			if (item_moved(&dot_dot_ih, &dot_dot_entry_path) ||
			    !entry_points_to_object("..", 2, &dot_dot_de,
						    old_dir)) {
				reiserfs_restore_prepared_buffer(old_inode->
								 i_sb,
								 old_de.de_bh);
				reiserfs_restore_prepared_buffer(old_inode->
								 i_sb,
								 new_de.de_bh);
				reiserfs_restore_prepared_buffer(old_inode->
								 i_sb,
								 dot_dot_de.
								 de_bh);
				continue;
			}
		}

		RFALSE(S_ISDIR(old_inode_mode) &&
		       !buffer_journal_prepared(dot_dot_de.de_bh), "");

		break;
	}

	/* ok, all the changes can be done in one fell swoop when we
	   have claimed all the buffers needed. */

	mark_de_visible(new_de.de_deh + new_de.de_entry_num);
	set_ino_in_dir_entry(&new_de, INODE_PKEY(old_inode));
	journal_mark_dirty(&th, old_dir->i_sb, new_de.de_bh);

	mark_de_hidden(old_de.de_deh + old_de.de_entry_num);
	journal_mark_dirty(&th, old_dir->i_sb, old_de.de_bh);
	ctime = CURRENT_TIME_SEC;
	old_dir->i_ctime = old_dir->i_mtime = ctime;
	new_dir->i_ctime = new_dir->i_mtime = ctime;
	/* thanks to Alex Adriaanse <*****@*****.**> for patch which adds ctime update of
	   renamed object */
	old_inode->i_ctime = ctime;

	if (new_dentry_inode) {
		// adjust link number of the victim
		if (S_ISDIR(new_dentry_inode->i_mode)) {
			clear_nlink(new_dentry_inode);
		} else {
			drop_nlink(new_dentry_inode);
		}
		new_dentry_inode->i_ctime = ctime;
		savelink = new_dentry_inode->i_nlink;
	}

	if (S_ISDIR(old_inode_mode)) {
		/* adjust ".." of renamed directory */
		set_ino_in_dir_entry(&dot_dot_de, INODE_PKEY(new_dir));
		journal_mark_dirty(&th, new_dir->i_sb, dot_dot_de.de_bh);

		if (!new_dentry_inode)
			/* there (in new_dir) was no directory, so it got new link
			   (".."  of renamed directory) */
			INC_DIR_INODE_NLINK(new_dir);

		/* old directory lost one link - ".. " of renamed directory */
		DEC_DIR_INODE_NLINK(old_dir);
	}
	// looks like in 2.3.99pre3 brelse is atomic. so we can use pathrelse
	pathrelse(&new_entry_path);
	pathrelse(&dot_dot_entry_path);

	// FIXME: this reiserfs_cut_from_item's return value may screw up
	// anybody, but it will panic if will not be able to find the
	// entry. This needs one more clean up
	if (reiserfs_cut_from_item
	    (&th, &old_entry_path, &(old_de.de_entry_key), old_dir, NULL,
	     0) < 0)
		reiserfs_error(old_dir->i_sb, "vs-7060",
			       "couldn't not cut old name. Fsck later?");

	old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;

	reiserfs_update_sd(&th, old_dir);
	reiserfs_update_sd(&th, new_dir);
	reiserfs_update_sd(&th, old_inode);

	if (new_dentry_inode) {
		if (savelink == 0)
			add_save_link(&th, new_dentry_inode,
				      0 /* not truncate */ );
		reiserfs_update_sd(&th, new_dentry_inode);
	}

	retval = journal_end(&th, old_dir->i_sb, jbegin_count);
	reiserfs_write_unlock(old_dir->i_sb);
	return retval;
}
Exemple #24
0
int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
{
  int error;
  struct inode * inode;
  struct path path_to_entry;
  struct reiserfs_dir_entry de;
  int windex ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
  int err;

  if (!dir)
    return -ENOENT;

  init_path (&path_to_entry);

  inode = get_empty_inode() ;
  if (!inode) {
    return -ENOSPC ;
  }
  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiserfs_mknod") ;
  de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) {
    pathrelse ( &path_to_entry);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput(inode) ;
    return -EEXIST;
  }

  pathrelse ( &path_to_entry);

  inode = reiserfs_new_inode (&th, dir, mode, 0, dentry, inode, &err);
  if (!inode) {
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    return err;
  }
  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  inode->i_uid = current->fsuid;
  inode->i_mode = mode;
  inode->i_op = NULL;

  if (S_ISREG(inode->i_mode))
    inode->i_op = &reiserfs_file_inode_operations;
  else if (S_ISDIR(inode->i_mode)) {
    inode->i_op = &reiserfs_dir_inode_operations;
    if (dir->i_mode & S_ISGID)
      inode->i_mode |= S_ISGID;
  }
  else if (S_ISLNK(inode->i_mode))
    inode->i_op = &reiserfs_symlink_inode_operations;
  else if (S_ISCHR(inode->i_mode))
    inode->i_op = &chrdev_inode_operations;
  else if (S_ISBLK(inode->i_mode))
    inode->i_op = &blkdev_inode_operations;
  else if (S_ISFIFO(inode->i_mode))
    init_fifo(inode);
  if (S_ISBLK(mode) || S_ISCHR(mode))
    inode->i_rdev = to_kdev_t(rdev);

  if_in_ram_update_sd (&th, inode);

  error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1);
  if (error) {
    inode->i_nlink--;
    if_in_ram_update_sd (&th, inode);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput (inode);
    return error;
  }
  if_in_ram_update_sd (&th, dir);
  d_instantiate(dentry, inode);
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  return 0;
}
Exemple #25
0
/* 
 * process, that is going to call fix_nodes/do_balance must hold only
 * one path. If it holds 2 or more, it can get into endless waiting in
 * get_empty_nodes or its clones 
 */
static int do_reiserfs_rename (struct reiserfs_transaction_handle *th, struct inode * old_dir, struct dentry *old_dentry,
			       struct inode * new_dir, struct dentry *new_dentry)
{
  int retval;
  struct path old_entry_path, new_entry_path, dot_dot_entry_path;
  struct reiserfs_dir_entry old_de, new_de, dot_dot_de;
  struct inode * old_inode, * new_inode;
  int new_entry_added = 0;

  init_path (&old_entry_path);
  init_path (&new_entry_path);
  init_path (&dot_dot_entry_path);
  goto start_up;

try_again:
  current->policy |= SCHED_YIELD;
  schedule();
	
start_up:
  old_inode = new_inode = NULL;
  dot_dot_de.de_bh = 0;
  new_de.de_bh = 0;

  /* 
   * look for the old name in old directory 
   */
  retval = -ENOENT;
  old_de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_entry_path, &old_de) == POSITION_NOT_FOUND)
    goto end_rename;

  pathrelse (&old_entry_path);

  old_inode = old_dentry->d_inode;
  retval = -EPERM;

  if ((old_dir->i_mode & S_ISVTX) && 
      current->fsuid != old_inode->i_uid &&
      current->fsuid != old_dir->i_uid && !fsuser())
    goto end_rename;

  new_inode = new_dentry->d_inode;

  /* look for the new entry in target directory */
  new_de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_entry_path, &new_de) == POSITION_FOUND) {
    if (!new_inode) {
      printk ("do_reiserfs_rename: new entry found, inode == 0 though\n");
    }
    /* this entry already exists, we can just set key of object */
    new_entry_added = 1;
  } else {
#ifdef REISERFS_CHECK
    if (new_entry_added) {
      if (new_de.de_namelen != new_dentry->d_name.len || memcmp (new_de.de_name, new_dentry->d_name.name, new_de.de_namelen) ||
	  de_visible (new_de.de_deh))
	reiserfs_panic (old_dir->i_sb, "vs-7045: reiserfs_rename: suspicious entry found");
    }
#endif /* REISERFS_CHECK */
  }
  pathrelse (&new_entry_path);


  if (new_inode == old_inode) {
    retval = 0;
    goto end_rename;
  }

  if (new_inode && S_ISDIR(new_inode->i_mode)) {
    /* new name exists and points to directory */
    retval = -EISDIR;
    if (!S_ISDIR(old_inode->i_mode))
      goto end_rename;
    retval = -EINVAL;
    if (is_subdir (new_dentry, old_dentry))
      goto end_rename;
    retval = -ENOTEMPTY;
    if (!reiserfs_empty_dir (new_inode))
      goto end_rename;
    retval = -EBUSY;
    if (new_inode->i_count > 1)
      goto end_rename;
  }

  retval = -EPERM;
  if (new_inode && (new_dir->i_mode & S_ISVTX) && 
      current->fsuid != new_inode->i_uid &&
      current->fsuid != new_dir->i_uid && !fsuser())
    goto end_rename;

  if (S_ISDIR(old_inode->i_mode)) {
    /* old name points to directory */
    retval = -ENOTDIR;
    if (new_inode && !S_ISDIR(new_inode->i_mode))
      goto end_rename;

    retval = -EINVAL;
    if (is_subdir(new_dentry, old_dentry))
      goto end_rename;

    retval = -EIO;
    /* directory is renamed, its parent directory will be changed, so find ".." entry */
    dot_dot_de.de_gen_number_bit_string = 0;
    if (reiserfs_find_entry (old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de) == POSITION_NOT_FOUND)
      goto end_rename;
    if (dot_dot_de.de_objectid != old_dir->i_ino)
      goto end_rename;
    pathrelse (&dot_dot_entry_path);

    retval = -EMLINK;
    if (!new_inode && new_dir->i_nlink >= REISERFS_LINK_MAX)
      goto end_rename;
  }
  
  if (new_entry_added == 0) {
    /* add new entry if we did not do it, but do not mark it as visible */
    retval = reiserfs_add_entry (th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len, INODE_PKEY (old_inode), &new_de, 0);
    if (retval)
      goto end_rename;
    if_in_ram_update_sd (th, new_dir);
    new_entry_added = 1;
    goto try_again;
  }


  /* 
   * look for old name, new name and ".." when renaming directories again
   */
  if (reiserfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_entry_path, &old_de) == POSITION_NOT_FOUND)
    reiserfs_panic (old_dir->i_sb, "vs-7050: reiserfs_rename: old name not found");
  if (reiserfs_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_entry_path, &new_de) == POSITION_NOT_FOUND)
    reiserfs_panic (old_dir->i_sb, "vs-7055: reiserfs_rename: new name not found");
  if (S_ISDIR(old_inode->i_mode) && reiserfs_find_entry (old_inode, "..", 2, &dot_dot_entry_path, &dot_dot_de) == POSITION_NOT_FOUND)
    reiserfs_panic (old_dir->i_sb, "vs-7060: reiserfs_rename: \"..\" name not found");
 

  /* sanity checking before doing the rename - avoid races */
  if (!entry_points_to_object (new_dentry->d_name.name, new_dentry->d_name.len, &new_de, new_inode))
    goto try_again;
  if (!entry_points_to_object (old_dentry->d_name.name, old_dentry->d_name.len, &old_de, old_inode))
    /* go to re-looking for old entry */
    goto try_again;

  if (S_ISDIR(old_inode->i_mode) && !entry_points_to_object ("..", 2, &dot_dot_de, old_dir))
    /* go to re-looking for ".." entry of renamed directory */
    goto try_again;
  
  /* ok, all the changes can be done in one fell swoop when we have
     claimed all the buffers needed.*/

  /* make old name hidden */
  mark_de_hidden (old_de.de_deh);
  journal_mark_dirty(th, old_dir->i_sb, old_de.de_bh) ;

  /* make new name visible and set key of old object (if entry
     existed, it is already visible, if not, key is correct already) */
  mark_de_visible (new_de.de_deh);
  new_de.de_deh->deh_dir_id = INODE_PKEY (old_inode)->k_dir_id;
  new_de.de_deh->deh_objectid = INODE_PKEY (old_inode)->k_objectid;
  journal_mark_dirty(th, old_dir->i_sb, new_de.de_bh) ;

  old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
  if_in_ram_update_sd (th, old_dir);

  new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
  if_in_ram_update_sd (th, new_dir);

  if (new_inode) {
    new_inode->i_nlink--;
    new_inode->i_ctime = CURRENT_TIME;
    if_in_ram_update_sd (th, new_inode);
  }
  if (dot_dot_de.de_bh) {
    set_ino_in_dir_entry (&dot_dot_de, INODE_PKEY (new_dir));
    journal_mark_dirty(th, old_dir->i_sb, dot_dot_de.de_bh) ;
    old_dir->i_nlink--;
    if_in_ram_update_sd (th, old_dir);
    if (new_inode) {
      new_inode->i_nlink--;
      if_in_ram_update_sd (th, new_inode);
    } else {
      new_dir->i_nlink++;
      if_in_ram_update_sd (th, new_dir);
    }
  }

  /* ok, renaming done */
  decrement_counters_in_path (&new_entry_path);
  decrement_counters_in_path (&dot_dot_entry_path);

  /* remove old name (it is hidden now) */
  if (reiserfs_cut_from_item (th, old_dir, old_dir->i_sb, &old_entry_path, &(old_de.de_entry_num),
			      &(old_de.de_entry_key), 0, PRESERVE_RENAMING) == 0)
    printk ("reiserfs_rename: could not remove old name\n");
  else {
    old_dir->i_size -= DEH_SIZE + old_de.de_entrylen;
    old_dir->i_blocks = old_dir->i_size / 512 + ((old_dir->i_size % 512) ? 1 : 0);
    if_in_ram_update_sd (th, old_dir);
  }

  /* Update the dcache */
  d_move(old_dentry, new_dentry);
  retval = 0;

end_rename:
  pathrelse (&old_entry_path);
  return retval;
}
Exemple #26
0
int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
{
  int error;
  struct inode * inode;
  struct path path_to_entry;
  struct reiserfs_dir_entry de;
  int windex ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
  int err;


  init_path (&path_to_entry);
  if (!dir || !dir->i_sb) {
    return -EINVAL;
  }
  inode = get_empty_inode() ;
  if (!inode) {
    return -ENOSPC ;
  }

  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiserfs_mkdir") ;
  de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) {
    pathrelse (&path_to_entry);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput(inode) ;
    return -EEXIST;
  }
  pathrelse (&path_to_entry);
  
  if (dir->i_nlink >= REISERFS_LINK_MAX) {
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput(inode) ;
    return -EMLINK;
  }
  
  mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
  if (dir->i_mode & S_ISGID)
    mode |= S_ISGID;
  inode = reiserfs_new_inode (&th, dir, mode, 0, dentry, inode, &err);
  if (!inode) {
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    return err;
  }
  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  inode->i_op = &reiserfs_dir_inode_operations;

  /* new inode and stat data are uptodate. Inode is clean. */
  error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1);
  if (error) {
    inode->i_nlink = 0;
    if_in_ram_update_sd (&th, inode);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput (inode);
    return error;
  }

  /* update dir inode, reiserfs_add_entry does not do that */
  dir->i_nlink ++;
  if_in_ram_update_sd (&th, dir);
  d_instantiate(dentry, inode);
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  return 0;
}
Exemple #27
0
int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
{
  struct inode * inode;
  int retval;
  struct reiserfs_dir_entry de;
  struct path path;
  struct super_block *s ;
  int windex ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 

  init_path (&path);

  retval = -ENOENT;
  de.de_gen_number_bit_string = 0;
  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiesrfs_rmdir") ;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path, &de) == POSITION_NOT_FOUND)
    goto end_rmdir;

  inode = dentry->d_inode;

  /* we don't need call this so early here, I'm just being cautious */
  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  retval = rmdir_not_allowed (dir, &de, inode);
  if (retval)
    goto end_rmdir;

  /* free preserve list if we should */
/*  maybe_free_preserve_list (dir->i_sb);*/

  if (!reiserfs_empty_dir (inode))
    retval = -ENOTEMPTY;
  else {
    /* cut entry from dir directory */
    if (reiserfs_cut_from_item (&th, dir, dir->i_sb, &path, &(de.de_entry_num), &(de.de_entry_key), 0, NOTHING_SPECIAL) == 0) {
      retval = -ENOENT;
    }
  }
  if (retval)
    goto end_rmdir;

  if (inode->i_nlink != 2)
    printk ("reiserfs_rmdir: empty directory has nlink != 2 (%d)\n", inode->i_nlink);
  inode->i_nlink = 0;
  inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  if_in_ram_update_sd (&th, inode);
  dir->i_nlink --;
  dir->i_size -= (DEH_SIZE + de.de_entrylen);
  if_in_ram_update_sd (&th, dir);

  s = dir->i_sb ;
  pop_journal_writer(windex) ;
  journal_end(&th, s, jbegin_count) ;
  d_delete(dentry); /* note, we've moved this after the journal end */
  return 0;
	
end_rmdir:
  /* we must release path, because we did not call reiserfs_cut_from_item, or reiserfs_cut_from_item
     does not release path if operation was not complete */
  pathrelse (&path);
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  return retval;	
}
Exemple #28
0
int
search_by_key(struct reiserfs_sb_info *p_s_sbi,
    const struct cpu_key * p_s_key, /* Key to search. */
    struct path * p_s_search_path,  /* This structure was allocated and
				       initialized by the calling function.
				       It is filled up by this function. */
    int n_stop_level)               /* How far down the tree to search. To
				       stop at leaf level - set to
				       DISK_LEAF_NODE_LEVEL */
{
	int error;
	int n_node_level, n_retval;
	int n_block_number, expected_level, fs_gen;
	struct path_element *p_s_last_element;
	struct buf *p_s_bp, *tmp_bp;

	/*
	 * As we add each node to a path we increase its count. This means that
	 * we must be careful to release all nodes in a path before we either
	 * discard the path struct or re-use the path struct, as we do here.
	 */
	decrement_counters_in_path(p_s_search_path);

	/*
	 * With each iteration of this loop we search through the items in the
	 * current node, and calculate the next current node(next path element)
	 * for the next iteration of this loop...
	 */
	n_block_number = SB_ROOT_BLOCK(p_s_sbi);
	expected_level = -1;

	reiserfs_log(LOG_DEBUG, "root block: #%d\n", n_block_number);

	while (1) {
		/* Prep path to have another element added to it. */
		reiserfs_log(LOG_DEBUG, "path element #%d\n",
		    p_s_search_path->path_length);
		p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path,
		    ++p_s_search_path->path_length);
		fs_gen = get_generation(p_s_sbi);

		/*
		 * Read the next tree node, and set the last element in the
		 * path to have a pointer to it.
		 */
		reiserfs_log(LOG_DEBUG, "reading block #%d\n",
		    n_block_number);
		if ((error = bread(p_s_sbi->s_devvp,
		    n_block_number * btodb(p_s_sbi->s_blocksize),
		    p_s_sbi->s_blocksize, NOCRED, &tmp_bp)) != 0) {
			reiserfs_log(LOG_DEBUG, "error reading block\n");
			p_s_search_path->path_length--;
			pathrelse(p_s_search_path);
			return (IO_ERROR);
		}
		reiserfs_log(LOG_DEBUG, "blkno = %ju, lblkno = %ju\n",
		    (intmax_t)tmp_bp->b_blkno, (intmax_t)tmp_bp->b_lblkno);

		/*
		 * As i didn't found a way to handle the lock correctly,
		 * i copy the data into a fake buffer
		 */
		reiserfs_log(LOG_DEBUG, "allocating p_s_bp\n");
		p_s_bp = malloc(sizeof *p_s_bp, M_REISERFSPATH, M_WAITOK);
		if (!p_s_bp) {
			reiserfs_log(LOG_DEBUG, "error allocating memory\n");
			p_s_search_path->path_length--;
			pathrelse(p_s_search_path);
			brelse(tmp_bp);
			return (IO_ERROR);
		}
		reiserfs_log(LOG_DEBUG, "copying struct buf\n");
		bcopy(tmp_bp, p_s_bp, sizeof(struct buf));

		reiserfs_log(LOG_DEBUG, "allocating p_s_bp->b_data\n");
		p_s_bp->b_data = malloc(p_s_sbi->s_blocksize,
		    M_REISERFSPATH, M_WAITOK);
		if (!p_s_bp->b_data) {
			reiserfs_log(LOG_DEBUG, "error allocating memory\n");
			p_s_search_path->path_length--;
			pathrelse(p_s_search_path);
			free(p_s_bp, M_REISERFSPATH);
			brelse(tmp_bp);
			return (IO_ERROR);
		}
		reiserfs_log(LOG_DEBUG, "copying buffer data\n");
		bcopy(tmp_bp->b_data, p_s_bp->b_data, p_s_sbi->s_blocksize);
		brelse(tmp_bp);
		tmp_bp = NULL;

		reiserfs_log(LOG_DEBUG, "...done\n");
		p_s_last_element->pe_buffer = p_s_bp;

		if (expected_level == -1)
			expected_level = SB_TREE_HEIGHT(p_s_sbi);
		expected_level--;
		reiserfs_log(LOG_DEBUG, "expected level: %d (%d)\n",
		    expected_level, SB_TREE_HEIGHT(p_s_sbi));

		/* XXX */ 
		/*
		 * It is possible that schedule occurred. We must check
		 * whether the key to search is still in the tree rooted
		 * from the current buffer. If not then repeat search
		 * from the root.
		 */
		if (fs_changed(fs_gen, p_s_sbi) &&
		    (!B_IS_IN_TREE(p_s_bp) ||
		     B_LEVEL(p_s_bp) != expected_level ||
		     !key_in_buffer(p_s_search_path, p_s_key, p_s_sbi))) {
			reiserfs_log(LOG_DEBUG,
			    "the key isn't in the tree anymore\n");
			decrement_counters_in_path(p_s_search_path);

			/*
			 * Get the root block number so that we can repeat
			 * the search starting from the root.
			 */
			n_block_number = SB_ROOT_BLOCK(p_s_sbi);
			expected_level = -1;

			/* Repeat search from the root */
			continue;
		}

		/*
		 * Make sure, that the node contents look like a node of
		 * certain level
		 */
		if (!is_tree_node(p_s_bp, expected_level)) {
			reiserfs_log(LOG_WARNING,
			    "invalid format found in block %ju. Fsck?",
			    (intmax_t)p_s_bp->b_blkno);
			pathrelse (p_s_search_path);
			return (IO_ERROR);
		}

		/* Ok, we have acquired next formatted node in the tree */
		n_node_level = B_LEVEL(p_s_bp);
		reiserfs_log(LOG_DEBUG, "block info:\n");
		reiserfs_log(LOG_DEBUG, "  node level:  %d\n",
		    n_node_level);
		reiserfs_log(LOG_DEBUG, "  nb of items: %d\n",
		    B_NR_ITEMS(p_s_bp));
		reiserfs_log(LOG_DEBUG, "  free space:  %d bytes\n",
		    B_FREE_SPACE(p_s_bp));
		reiserfs_log(LOG_DEBUG, "bin_search with :\n"
		    "  p_s_key = (objectid=%d, dirid=%d)\n"
		    "  B_NR_ITEMS(p_s_bp) = %d\n"
		    "  p_s_last_element->pe_position = %d (path_length = %d)\n",
		    p_s_key->on_disk_key.k_objectid,
		    p_s_key->on_disk_key.k_dir_id,
		    B_NR_ITEMS(p_s_bp),
		    p_s_last_element->pe_position,
		    p_s_search_path->path_length);
		n_retval = bin_search(p_s_key, B_N_PITEM_HEAD(p_s_bp, 0),
		    B_NR_ITEMS(p_s_bp),
		    (n_node_level == DISK_LEAF_NODE_LEVEL) ? IH_SIZE : KEY_SIZE,
		    &(p_s_last_element->pe_position));
		reiserfs_log(LOG_DEBUG, "bin_search result: %d\n",
		    n_retval);
		if (n_node_level == n_stop_level) {
			reiserfs_log(LOG_DEBUG, "stop level reached (%s)\n",
			    n_retval == ITEM_FOUND ? "found" : "not found");
			return (n_retval);
		}

		/* We are not in the stop level */
		if (n_retval == ITEM_FOUND)
			/*
			 * Item has been found, so we choose the pointer
			 * which is to the right of the found one
			 */
			p_s_last_element->pe_position++;

		/*
		 * If item was not found we choose the position which is
		 * to the left of the found item. This requires no code,
		 * bin_search did it already.
		 */

		/*
		 * So we have chosen a position in the current node which
		 * is an internal node. Now we calculate child block number
		 * by position in the node.
		 */
		n_block_number = B_N_CHILD_NUM(p_s_bp,
		    p_s_last_element->pe_position);
	}

	reiserfs_log(LOG_DEBUG, "done\n");
	return (0);
}
Exemple #29
0
static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldir)
{
    struct inode *inode = filp->f_dentry->d_inode;
    struct cpu_key pos_key;	/* key of current position in the directory (key of directory entry) */
    INITIALIZE_PATH (path_to_entry);
    struct buffer_head * bh;
    int item_num, entry_num;
    const struct key * rkey;
    struct item_head * ih, tmp_ih;
    int search_res;
    char * local_buf;
    loff_t next_pos;
    char small_buf[32] ; /* avoid kmalloc if we can */
    struct reiserfs_dir_entry de;


    reiserfs_check_lock_depth("readdir") ;

    /* form key for search the next directory entry using f_pos field of
       file structure */
    make_cpu_key (&pos_key, inode, (filp->f_pos) ? (filp->f_pos) : DOT_OFFSET,
		  TYPE_DIRENTRY, 3);
    next_pos = cpu_key_k_offset (&pos_key);

    /*  reiserfs_warning ("reiserfs_readdir 1: f_pos = %Ld\n", filp->f_pos);*/

    while (1) {
    research:
	/* search the directory item, containing entry with specified key */
	search_res = search_by_entry_key (inode->i_sb, &pos_key, &path_to_entry, &de);
	if (search_res == IO_ERROR) {
	    // FIXME: we could just skip part of directory which could
	    // not be read
	    return -EIO;
	}
	entry_num = de.de_entry_num;
	bh = de.de_bh;
	item_num = de.de_item_num;
	ih = de.de_ih;
	store_ih (&tmp_ih, ih);
		
	/* we must have found item, that is item of this directory, */
	RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key),
		"vs-9000: found item %h does not match to dir we readdir %K",
		ih, &pos_key);
	RFALSE( item_num > B_NR_ITEMS (bh) - 1,
		"vs-9005 item_num == %d, item amount == %d", 
		item_num, B_NR_ITEMS (bh));
      
	/* and entry must be not more than number of entries in the item */
	RFALSE( I_ENTRY_COUNT (ih) < entry_num,
		"vs-9010: entry number is too big %d (%d)", 
		entry_num, I_ENTRY_COUNT (ih));

	if (search_res == POSITION_FOUND || entry_num < I_ENTRY_COUNT (ih)) {
	    /* go through all entries in the directory item beginning from the entry, that has been found */
	    struct reiserfs_de_head * deh = B_I_DEH (bh, ih) + entry_num;

	    for (; entry_num < I_ENTRY_COUNT (ih); entry_num ++, deh ++) {
		int d_reclen;
		char * d_name;
		off_t d_off;
		ino_t d_ino;

		if (!de_visible (deh))
		    /* it is hidden entry */
		    continue;
		d_reclen = entry_length (bh, ih, entry_num);
		d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh);
		if (!d_name[d_reclen - 1])
		    d_reclen = strlen (d_name);
	
		if (d_reclen > REISERFS_MAX_NAME_LEN(inode->i_sb->s_blocksize)){
		    /* too big to send back to VFS */
		    continue ;
		}
		d_off = deh_offset (deh);
		filp->f_pos = d_off ;
		d_ino = deh_objectid (deh);
		if (d_reclen <= 32) {
		  local_buf = small_buf ;
		} else {
		    local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ;
		    if (!local_buf) {
			pathrelse (&path_to_entry);
			return -ENOMEM ;
		    }
		    if (item_moved (&tmp_ih, &path_to_entry)) {
			reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
			goto research;
		    }
		}
		// Note, that we copy name to user space via temporary
		// buffer (local_buf) because filldir will block if
		// user space buffer is swapped out. At that time
		// entry can move to somewhere else
		memcpy (local_buf, d_name, d_reclen);
		if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, 
		             DT_UNKNOWN) < 0) {
		    if (local_buf != small_buf) {
			reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
		    }
		    goto end;
		}
		if (local_buf != small_buf) {
		    reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ;
		}

		// next entry should be looked for with such offset
		next_pos = deh_offset (deh) + 1;

		if (item_moved (&tmp_ih, &path_to_entry)) {
		    goto research;
		}
	    } /* for */
	}

	if (item_num != B_NR_ITEMS (bh) - 1)
	    // end of directory has been reached
	    goto end;

	/* item we went through is last item of node. Using right
	   delimiting key check is it directory end */
	rkey = get_rkey (&path_to_entry, inode->i_sb);
	if (! comp_le_keys (rkey, &MIN_KEY)) {
	    /* set pos_key to key, that is the smallest and greater
	       that key of the last entry in the item */
	    set_cpu_key_k_offset (&pos_key, next_pos);
	    continue;
	}

	if ( COMP_SHORT_KEYS (rkey, &pos_key)) {
	    // end of directory has been reached
	    goto end;
	}
	
	/* directory continues in the right neighboring block */
	set_cpu_key_k_offset (&pos_key, le_key_k_offset (KEY_FORMAT_3_5, rkey));

    } /* while */


 end:
    // FIXME: ext2_readdir does not reset f_pos
    filp->f_pos = next_pos;
    pathrelse (&path_to_entry);
    reiserfs_check_path(&path_to_entry) ;
    UPDATE_ATIME(inode) ;
    return 0;
}
Exemple #30
0
int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const char * symname)
{
  struct inode * inode;
  struct path path_to_entry;
  struct reiserfs_dir_entry de;
  int error;
  int windex ;
  struct reiserfs_transaction_handle th ;
  int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; 
  int err;

  init_path (&path_to_entry);
  if (strlen (symname) + 1 + SD_SIZE > MAX_ITEM_LEN (dir->i_sb->s_blocksize)) {
    return -ENAMETOOLONG;
  }
  inode = get_empty_inode() ;
  if (!inode) {
    return -ENOSPC ;
  }
 
  journal_begin(&th, dir->i_sb, jbegin_count) ;
  windex = push_journal_writer("reiserfs_symlink") ;
  inode = reiserfs_new_inode (&th, dir, S_IFLNK, symname, dentry, inode, &err);
  if (inode == 0) {
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    return err;
  }
  reiserfs_update_inode_transaction(inode) ;
  reiserfs_update_inode_transaction(dir) ;

  inode->i_op = &reiserfs_symlink_inode_operations;
  inode->i_size = strlen (symname);
  inode->i_mode = S_IFLNK | 0777;
  if_in_ram_update_sd (&th, inode);

  de.de_gen_number_bit_string = 0;
  if (reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de) == POSITION_FOUND) {
    pathrelse (&path_to_entry);
    inode->i_nlink--;
    if_in_ram_update_sd (&th, inode);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput (inode);
    return -EEXIST;
  }
  pathrelse (&path_to_entry);

  error = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, INODE_PKEY (inode), &de, 1);
  if (error) {
    inode->i_nlink--;
    if_in_ram_update_sd (&th, inode);
    pop_journal_writer(windex) ;
    journal_end(&th, dir->i_sb, jbegin_count) ;
    iput (inode);
    return error;
  }
  if_in_ram_update_sd (&th, dir);
  d_instantiate(dentry, inode);
  pop_journal_writer(windex) ;
  journal_end(&th, dir->i_sb, jbegin_count) ;
  return 0;
}