Ejemplo n.º 1
0
static int
get_root_node(struct reiserfs_mount *rmp, struct reiserfs_node **root)
{
	struct reiserfs_node *ip;
	struct reiserfs_iget_args args;

	/* Allocate the node structure */
	reiserfs_log(LOG_DEBUG, "malloc(struct reiserfs_node)\n");
	ip = malloc(sizeof(struct reiserfs_node),
	    M_REISERFSNODE, M_WAITOK | M_ZERO);

	/* Fill the structure */
	reiserfs_log(LOG_DEBUG, "filling *ip\n");
	ip->i_dev      = rmp->rm_dev;
	ip->i_number   = REISERFS_ROOT_OBJECTID;
	ip->i_ino      = REISERFS_ROOT_PARENT_OBJECTID;
	ip->i_reiserfs = rmp->rm_reiserfs;

	/* Read the inode */
	args.objectid = ip->i_number;
	args.dirid    = ip->i_ino;
	reiserfs_log(LOG_DEBUG, "call reiserfs_read_locked_inode("
	    "objectid=%d,dirid=%d)\n", args.objectid, args.dirid);
	reiserfs_read_locked_inode(ip, &args);

	ip->i_devvp = rmp->rm_devvp;
	//XXX VREF(ip->i_devvp); Is it necessary ?

	*root = ip;
	return (0);
}
Ejemplo n.º 2
0
/* Returns 1 if buf looks like an internal node, 0 otherwise */
static int
is_internal(char *buf, int blocksize, struct buf *bp)
{
	int nr, used_space;
	struct block_head *blkh;

	blkh = (struct block_head *)buf;
	nr   = blkh_level(blkh);
	if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
		/* This level is not possible for internal nodes */
		reiserfs_log(LOG_WARNING, "this should be caught earlier\n");
		return (0);
	}

	nr = blkh_nr_item(blkh);
	if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
		/*
		 * For internal which is not root we might check min
		 * number of keys
		 */
		reiserfs_log(LOG_WARNING, "number of key seems wrong\n");
		return (0);
	}

	used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
	if (used_space != blocksize - blkh_free_space(blkh)) {
		reiserfs_log(LOG_WARNING,
		    "is_internal: free space seems wrong\n");
		return (0);
	}

	/* One may imagine much more checks */
	return (1);
}
Ejemplo n.º 3
0
/*
 * 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) */
}
static int
direntry_bytes_number(struct item_head *ih, int block_size)
{

	reiserfs_log(LOG_WARNING, "bytes number is asked for direntry\n");
	return (0);
}
static int
errcatch_bytes_number(struct item_head *ih, int block_size)
{

	reiserfs_log(LOG_WARNING, "invalid item type observed, run fsck ASAP");
	return (0);
}
Ejemplo n.º 6
0
int
reiserfs_check_path(struct path *p)
{

	if (p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET)
		reiserfs_log(LOG_WARNING, "path not properly relsed\n");
	return (0);
}
Ejemplo n.º 7
0
/* Return target name of a symbolic link */
static int
reiserfs_readlink(struct vop_readlink_args *ap)
{
    struct vnode *vp = ap->a_vp;

    reiserfs_log(LOG_DEBUG, "redirect to VOP_READ()\n");
    return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
}
Ejemplo n.º 8
0
/*
 * 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);
}
Ejemplo n.º 9
0
/*
 * File handle to vnode
 *
 * Have to be really careful about stale file handles:
 * - check that the inode key is valid
 * - call ffs_vget() to get the locked inode
 * - check for an unallocated inode (i_mode == 0)
 * - check that the given client host has export rights and return
 *   those rights via. exflagsp and credanonp
 */
static int
reiserfs_fhtovp(struct mount *mp, struct fid *fhp, int flags,
    struct vnode **vpp)
{
	int error;
	struct rfid *rfhp;
	struct vnode *nvp;
	struct cpu_key key;
	struct reiserfs_node *ip;
	struct reiserfs_sb_info *sbi;
	struct thread *td = curthread;

	rfhp = (struct rfid *)fhp;
	sbi  = VFSTOREISERFS(mp)->rm_reiserfs;

	/* Check that the key is valid */
	if (rfhp->rfid_dirid < REISERFS_ROOT_PARENT_OBJECTID &&
	    rfhp->rfid_objectid < REISERFS_ROOT_OBJECTID)
		return (ESTALE);

	reiserfs_log(LOG_DEBUG,
	    "file handle key is (dirid=%d, objectid=%d)\n",
	    rfhp->rfid_dirid, rfhp->rfid_objectid);
	key.on_disk_key.k_dir_id   = rfhp->rfid_dirid;
	key.on_disk_key.k_objectid = rfhp->rfid_objectid;

	reiserfs_log(LOG_DEBUG, "read this inode\n");
	error = reiserfs_iget(mp, &key, &nvp, td);
	if (error) {
		*vpp = NULLVP;
		return (error);
	}

	reiserfs_log(LOG_DEBUG, "check validity\n");
	ip = VTOI(nvp);
	if (ip->i_mode == 0 || ip->i_generation != rfhp->rfid_gen) {
		vput(nvp);
		*vpp = NULLVP;
		return (ESTALE);
	}

	reiserfs_log(LOG_DEBUG, "return it\n");
	*vpp = nvp;
	return (0);
}
Ejemplo n.º 10
0
/* Return pointer to appropriate function */
static hashf_t
hash_function(struct reiserfs_mount *rmp)
{

	switch (what_hash(rmp)) {
	case TEA_HASH:
		reiserfs_log(LOG_INFO, "using tea hash to sort names\n");
		return (keyed_hash);
	case YURA_HASH:
		reiserfs_log(LOG_INFO, "using rupasov hash to sort names\n");
		return (yura_hash);
	case R5_HASH:
		reiserfs_log(LOG_INFO, "using r5 hash to sort names\n");
		return (r5_hash);
	}

	return (NULL);
}
Ejemplo n.º 11
0
/* What entry points to */
static inline void
set_de_object_key(struct reiserfs_dir_entry *de)
{

	if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
		reiserfs_log(LOG_DEBUG, "BUG\n");
		return;
	}
	de->de_dir_id   = deh_dir_id(&(de->de_deh[de->de_entry_num]));
	de->de_objectid = deh_objectid(&(de->de_deh[de->de_entry_num]));
}
Ejemplo n.º 12
0
/*
 * Read the bitmaps
 */
static int
read_bitmaps(struct reiserfs_mount *rmp)
{
	int i, bmap_nr;
	struct buf *bp = NULL;
	struct reiserfs_sb_info *sbi = rmp->rm_reiserfs;

	/* Allocate memory for the table of bitmaps */
	SB_AP_BITMAP(sbi) =
	    malloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(sbi),
		M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!SB_AP_BITMAP(sbi))
		return (ENOMEM);

	/* Read all the bitmaps */
	for (i = 0,
	    bmap_nr = (REISERFS_DISK_OFFSET_IN_BYTES / sbi->s_blocksize + 1) *
	    btodb(sbi->s_blocksize);
	    i < SB_BMAP_NR(sbi); i++, bmap_nr = sbi->s_blocksize * 8 * i) {
		SB_AP_BITMAP(sbi)[i].bp_data = malloc(sbi->s_blocksize,
		    M_REISERFSMNT, M_WAITOK | M_ZERO);
		if (!SB_AP_BITMAP(sbi)[i].bp_data)
			return (ENOMEM);
		bread(rmp->rm_devvp, bmap_nr, sbi->s_blocksize, NOCRED, &bp);
		bcopy(bp->b_data, SB_AP_BITMAP(sbi)[i].bp_data,
		    sbi->s_blocksize);
		brelse(bp);
		bp = NULL;

		/*if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh))
			ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh);*/
	}

	for (i = 0; i < SB_BMAP_NR(sbi); i++) {
		/*if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) {
		  reiserfs_warning(s,"sh-2029: reiserfs read_bitmaps: "
		  "bitmap block (#%lu) reading failed",
		  SB_AP_BITMAP(s)[i].bh->b_blocknr);
		  for (i = 0; i < SB_BMAP_NR(s); i++)
		  brelse(SB_AP_BITMAP(s)[i].bh);
		  vfree(SB_AP_BITMAP(s));
		  SB_AP_BITMAP(s) = NULL;
		  return 1;
		  }*/
		load_bitmap_info_data(sbi, SB_AP_BITMAP(sbi) + i);
		reiserfs_log(LOG_DEBUG,
		    "%d free blocks (starting at block %ld)\n",
		    SB_AP_BITMAP(sbi)[i].free_count,
		    (long)SB_AP_BITMAP(sbi)[i].first_zero_hint);
	}

	return (0);
}
Ejemplo n.º 13
0
static int
reiserfs_access(struct vop_access_args *ap)
{
    int error;
    struct vnode *vp = ap->a_vp;
    struct reiserfs_node *ip = VTOI(vp);
    accmode_t accmode = ap->a_accmode;

    /*
     * Disallow write attempts on read-only file systems; unless the file
     * is a socket, fifo, or a block or character device resident on the
     * file system.
     */
    if (accmode & VWRITE) {
        switch (vp->v_type) {
        case VDIR:
        case VLNK:
        case VREG:
            if (vp->v_mount->mnt_flag & MNT_RDONLY) {
                reiserfs_log(LOG_DEBUG,
                             "no write access (read-only fs)\n");
                return (EROFS);
            }
            break;
        default:
            break;
        }
    }

    /* If immutable bit set, nobody gets to write it. */
    if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) {
        reiserfs_log(LOG_DEBUG, "no write access (immutable)\n");
        return (EPERM);
    }

    error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
                    ap->a_accmode, ap->a_cred, NULL);
    return (error);
}
Ejemplo n.º 14
0
/*
 * Make sure that bh contains formatted node of reiserfs tree of
 * 'level'-th level
 */
static int
is_tree_node(struct buf *bp, int level)
{
	if (B_LEVEL(bp) != level) {
		reiserfs_log(LOG_WARNING,
		    "node level (%d) doesn't match to the "
		    "expected one (%d)\n", B_LEVEL (bp), level);
		return (0);
	}

	if (level == DISK_LEAF_NODE_LEVEL)
		return (is_leaf(bp->b_data, bp->b_bcount, bp));

	return (is_internal(bp->b_data, bp->b_bcount, bp));
}
Ejemplo n.º 15
0
/*
 * de_bh, de_ih, de_deh (points to first element of array), de_item_num
 * is set
 */
void
set_de_name_and_namelen(struct reiserfs_dir_entry *de)
{
	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;

	if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
		reiserfs_log(LOG_DEBUG, "BUG\n");
		return;
	}

	de->de_entrylen = entry_length(de->de_bp, de->de_ih, de->de_entry_num);
	de->de_namelen  = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0);
	de->de_name     = B_I_PITEM(de->de_bp, de->de_ih) + deh_location(deh);
	if (de->de_name[de->de_namelen - 1] == 0)
		de->de_namelen = strlen(de->de_name);
}
Ejemplo n.º 16
0
static inline void
store_de_entry_key(struct reiserfs_dir_entry *de)
{
	struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num;

	if (de->de_entry_num >= ih_entry_count(de->de_ih)) {
		reiserfs_log(LOG_DEBUG, "BUG\n"); 
		return;
	}

	/* Store key of the found entry */
	de->de_entry_key.version = KEY_FORMAT_3_5;
	de->de_entry_key.on_disk_key.k_dir_id =
	    le32toh(de->de_ih->ih_key.k_dir_id);
	de->de_entry_key.on_disk_key.k_objectid =
	    le32toh(de->de_ih->ih_key.k_objectid);
	set_cpu_key_k_offset(&(de->de_entry_key), deh_offset(deh));
	set_cpu_key_k_type(&(de->de_entry_key), TYPE_DIRENTRY);
}
Ejemplo n.º 17
0
/* The function is NOT SCHEDULE-SAFE! */
int
search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi,
    const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */
    struct path *p_s_search_path)    /* Filled up by this function.  */
{
	int retval, n_blk_size;
	off_t item_offset, offset;
	struct item_head *p_le_ih; /* Pointer to on-disk structure */
	struct reiserfs_dir_entry de;

	/* If searching for directory entry. */
	if (is_direntry_cpu_key(p_cpu_key))
		return (search_by_entry_key(p_s_sbi, p_cpu_key,
		    p_s_search_path, &de));

	/* If not searching for directory entry. */

	/* If item is found. */
	retval = search_item(p_s_sbi, p_cpu_key, p_s_search_path);
	if (retval == IO_ERROR)
		return (retval);
	if (retval == ITEM_FOUND) {
		if (ih_item_len(B_N_PITEM_HEAD(
		    PATH_PLAST_BUFFER(p_s_search_path),
		    PATH_LAST_POSITION(p_s_search_path))) == 0) {
			reiserfs_log(LOG_WARNING, "item length equals zero\n");
		}

		pos_in_item(p_s_search_path) = 0;
		return (POSITION_FOUND);
	}

	if (PATH_LAST_POSITION(p_s_search_path) == 0) {
		reiserfs_log(LOG_WARNING, "position equals zero\n");
	}

	/* Item is not found. Set path to the previous item. */
	p_le_ih = B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_search_path),
	    --PATH_LAST_POSITION(p_s_search_path));
	n_blk_size = p_s_sbi->s_blocksize;

	if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
		return (FILE_NOT_FOUND);
	}

	item_offset = le_ih_k_offset(p_le_ih);
	offset = cpu_key_k_offset(p_cpu_key);

	/* Needed byte is contained in the item pointed to by the path.*/
	if (item_offset <= offset &&
	    item_offset + op_bytes_number(p_le_ih, n_blk_size) > offset) {
		pos_in_item(p_s_search_path) = offset - item_offset;
		if (is_indirect_le_ih(p_le_ih)) {
			pos_in_item(p_s_search_path) /= n_blk_size;
		}
		return (POSITION_FOUND);
	}

	/* Needed byte is not contained in the item pointed to by the
	 * path. Set pos_in_item out of the item. */
	if (is_indirect_le_ih(p_le_ih))
		pos_in_item(p_s_search_path) =
		    ih_item_len(p_le_ih) / UNFM_P_SIZE;
	else
		pos_in_item(p_s_search_path) =
		    ih_item_len(p_le_ih);

	return (POSITION_NOT_FOUND);
}
Ejemplo n.º 18
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);
}
Ejemplo n.º 19
0
/* Finds out which hash names are sorted with */
static int
what_hash(struct reiserfs_mount *rmp)
{
	uint32_t code;
	struct reiserfs_sb_info *sbi = rmp->rm_reiserfs;

	find_hash_out(rmp);
	code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(sbi));

	/*
	 * reiserfs_hash_detect() == true if any of the hash mount options
	 * were used. We must check them to make sure the user isn't using a
	 * bad hash value
	 */
	if (code == UNSET_HASH || reiserfs_hash_detect(sbi))
		code = find_hash_out(rmp);

	if (code != UNSET_HASH && reiserfs_hash_detect(sbi)) {
		/*
		 * Detection has found the hash, and we must check against
		 * the mount options
		 */
		if (reiserfs_rupasov_hash(sbi) && code != YURA_HASH) {
			reiserfs_log(LOG_ERR, "error, %s hash detected, "
			    "unable to force rupasov hash",
			    reiserfs_hashname(code));
			code = UNSET_HASH;
		} else if (reiserfs_tea_hash(sbi) && code != TEA_HASH) {
			reiserfs_log(LOG_ERR, "error, %s hash detected, "
			    "unable to force tea hash",
			    reiserfs_hashname(code));
			code = UNSET_HASH;
		} else if (reiserfs_r5_hash(sbi) && code != R5_HASH) {
			reiserfs_log(LOG_ERR, "error, %s hash detected, "
			    "unable to force r5 hash",
			    reiserfs_hashname(code));
			code = UNSET_HASH;
		}
	} else {
		/*
		 * Find_hash_out was not called or could not determine
		 * the hash
		 */
		if (reiserfs_rupasov_hash(sbi)) {
			code = YURA_HASH;
		} else if (reiserfs_tea_hash(sbi)) {
			code = TEA_HASH;
		} else if (reiserfs_r5_hash(sbi)) {
			code = R5_HASH;
		}
	}

	/* TODO Not supported yet */
#if 0
	/* If we are mounted RW, and we have a new valid hash code, update
	 * the super */
	if (code != UNSET_HASH &&
	    !(s->s_flags & MS_RDONLY) &&
	    code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) {
		set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code);
	}
#endif

	return (code);
}
Ejemplo n.º 20
0
static int
is_leaf(char *buf, int blocksize, struct buf *bp)
{
	struct item_head *ih;
	struct block_head *blkh;
	int used_space, prev_location, i, nr;

	blkh = (struct block_head *)buf;
	if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
		reiserfs_log(LOG_WARNING, "this should be caught earlier");
		return (0);
	}

	nr = blkh_nr_item(blkh);
	if (nr < 1 || nr >
	    ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
		/* Item number is too big or too small */
		reiserfs_log(LOG_WARNING, "nr_item seems wrong\n");
		return (0);
	}

	ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
	used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location(ih));
	if (used_space != blocksize - blkh_free_space(blkh)) {
		/*
		 * Free space does not match to calculated amount of
		 * use space
		 */
		reiserfs_log(LOG_WARNING, "free space seems wrong\n");
		return (0);
	}

	/* FIXME: it is_leaf will hit performance too much - we may have
	 * return 1 here */

	/* Check tables of item heads */
	ih = (struct item_head *)(buf + BLKH_SIZE);
	prev_location = blocksize;
	for (i = 0; i < nr; i++, ih++) {
		if (le_ih_k_type(ih) == TYPE_ANY) {
			reiserfs_log(LOG_WARNING,
			    "wrong item type for item\n");
			return (0);
		}
		if (ih_location(ih) >= blocksize ||
		    ih_location(ih) < IH_SIZE * nr) {
			reiserfs_log(LOG_WARNING,
			    "item location seems wrong\n");
			return (0);
		}
		if (ih_item_len(ih) < 1 ||
		    ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
			reiserfs_log(LOG_WARNING, "item length seems wrong\n");
			return (0);
		}
		if (prev_location - ih_location(ih) != ih_item_len(ih)) {
			reiserfs_log(LOG_WARNING,
			    "item location seems wrong (second one)\n");
			return (0);
		}
		prev_location = ih_location(ih);
	}

	/* One may imagine much more checks */
	return 1;
}
Ejemplo n.º 21
0
/*
 * Unmount system call
 */
static int
reiserfs_unmount(struct mount *mp, int mntflags)
{
	int error, flags = 0;
	struct reiserfs_mount *rmp;
	struct reiserfs_sb_info *sbi;

	reiserfs_log(LOG_DEBUG, "get private data\n");
	rmp = VFSTOREISERFS(mp);
	sbi = rmp->rm_reiserfs;

	/* Flangs handling */
	reiserfs_log(LOG_DEBUG, "handle mntflags\n");
	if (mntflags & MNT_FORCE)
		flags |= FORCECLOSE;

	/* Flush files -> vflush */
	reiserfs_log(LOG_DEBUG, "flush vnodes\n");
	if ((error = vflush(mp, 0, flags, curthread)))
		return (error);

	/* XXX Super block update */

	if (sbi) {
		if (SB_AP_BITMAP(sbi)) {
			int i;
			reiserfs_log(LOG_DEBUG,
			    "release bitmap buffers (total: %d)\n",
			    SB_BMAP_NR(sbi));
			for (i = 0; i < SB_BMAP_NR(sbi); i++) {
				if (SB_AP_BITMAP(sbi)[i].bp_data) {
					free(SB_AP_BITMAP(sbi)[i].bp_data,
					    M_REISERFSMNT);
					SB_AP_BITMAP(sbi)[i].bp_data = NULL;
				}
			}

			reiserfs_log(LOG_DEBUG, "free bitmaps structure\n");
			free(SB_AP_BITMAP(sbi), M_REISERFSMNT);
			SB_AP_BITMAP(sbi) = NULL;
		}

		if (sbi->s_rs) {
			reiserfs_log(LOG_DEBUG, "free super block data\n");
			free(sbi->s_rs, M_REISERFSMNT);
			sbi->s_rs = NULL;
		}
	}

	reiserfs_log(LOG_DEBUG, "close device\n");
#if defined(si_mountpoint)
	rmp->rm_devvp->v_rdev->si_mountpoint = NULL;
#endif

	DROP_GIANT();
	g_topology_lock();
	g_vfs_close(rmp->rm_cp);
	g_topology_unlock();
	PICKUP_GIANT();
	vrele(rmp->rm_devvp);
	dev_rel(rmp->rm_dev);

	if (sbi) {
		reiserfs_log(LOG_DEBUG, "free sbi\n");
		free(sbi, M_REISERFSMNT);
		sbi = rmp->rm_reiserfs = NULL;
	}
	if (rmp) {
		reiserfs_log(LOG_DEBUG, "free rmp\n");
		free(rmp, M_REISERFSMNT);
		rmp = NULL;
	}

	mp->mnt_data  = 0;
	MNT_ILOCK(mp);
	mp->mnt_flag &= ~MNT_LOCAL;
	MNT_IUNLOCK(mp);

	reiserfs_log(LOG_DEBUG, "done\n");
	return (error);
}
Ejemplo n.º 22
0
/*
 * The statfs syscall
 */
static int
reiserfs_statfs(struct mount *mp, struct statfs *sbp)
{
	struct reiserfs_mount *rmp;
	struct reiserfs_sb_info *sbi;
	struct reiserfs_super_block *rs;

	reiserfs_log(LOG_DEBUG, "get private data\n");
	rmp = VFSTOREISERFS(mp);
	sbi = rmp->rm_reiserfs;
	rs  = sbi->s_rs;

	reiserfs_log(LOG_DEBUG, "fill statfs structure\n");
	sbp->f_bsize  = sbi->s_blocksize;
	sbp->f_iosize = sbp->f_bsize;
	sbp->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
	sbp->f_bfree  = sb_free_blocks(rs);
	sbp->f_bavail = sbp->f_bfree;
	sbp->f_files  = 0;
	sbp->f_ffree  = 0;
	reiserfs_log(LOG_DEBUG, "  block size   = %ju\n",
	    (intmax_t)sbp->f_bsize);
	reiserfs_log(LOG_DEBUG, "  IO size      = %ju\n",
	    (intmax_t)sbp->f_iosize);
	reiserfs_log(LOG_DEBUG, "  block count  = %ju\n",
	    (intmax_t)sbp->f_blocks);
	reiserfs_log(LOG_DEBUG, "  free blocks  = %ju\n",
	    (intmax_t)sbp->f_bfree);
	reiserfs_log(LOG_DEBUG, "  avail blocks = %ju\n",
	    (intmax_t)sbp->f_bavail);
	reiserfs_log(LOG_DEBUG, "...done\n");

	if (sbp != &mp->mnt_stat) {
		reiserfs_log(LOG_DEBUG, "copying monut point info\n");
		sbp->f_type = mp->mnt_vfc->vfc_typenum;
		bcopy((caddr_t)mp->mnt_stat.f_mntonname,
		    (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
		    (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
		reiserfs_log(LOG_DEBUG, "  mount from: %s\n",
		    sbp->f_mntfromname);
		reiserfs_log(LOG_DEBUG, "  mount on:   %s\n",
		    sbp->f_mntonname);
		reiserfs_log(LOG_DEBUG, "...done\n");
	}

	return (0);
}
Ejemplo n.º 23
0
/*
 * de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already
 * Used when hash collisions exist
 */
static int
linear_search_in_dir_item(struct cpu_key *key, struct reiserfs_dir_entry *de,
    const char *name, int namelen)
{
	int i;
	int retval;
	struct reiserfs_de_head * deh = de->de_deh;

	i = de->de_entry_num;

	if (i == I_ENTRY_COUNT(de->de_ih) ||
	    GET_HASH_VALUE(deh_offset(deh + i)) !=
	    GET_HASH_VALUE(cpu_key_k_offset(key))) {
		i--;
	}

	/*RFALSE( de->de_deh != B_I_DEH (de->de_bh, de->de_ih),
	  "vs-7010: array of entry headers not found");*/

	deh += i;

	for (; i >= 0; i--, deh--) {
		if (GET_HASH_VALUE(deh_offset(deh)) !=
		    GET_HASH_VALUE(cpu_key_k_offset(key))) {
			/*
			 * Hash value does not match, no need to check
			 * whole name
			 */
			reiserfs_log(LOG_DEBUG, "name `%s' not found\n", name);
			return (NAME_NOT_FOUND);
		}

		/* Mark that this generation number is used */
		if (de->de_gen_number_bit_string)
			set_bit(GET_GENERATION_NUMBER(deh_offset(deh)),
			    (unsigned long *)de->de_gen_number_bit_string);

		/* Calculate pointer to name and namelen */
		de->de_entry_num = i;
		set_de_name_and_namelen(de);

		if ((retval = reiserfs_match(de, name, namelen)) !=
		    NAME_NOT_FOUND) {
			/*
			 * de's de_name, de_namelen, de_recordlen are set.
			 * Fill the rest:
			 */
			/* key of pointed object */
			set_de_object_key(de);
			store_de_entry_key(de);

			/* retval can be NAME_FOUND or NAME_FOUND_INVISIBLE */
			reiserfs_log(LOG_DEBUG,
			    "reiserfs_match answered `%d'\n",
			    retval);
			return (retval);
		}
	}

	if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0)
		/*
		 * We have reached left most entry in the node. In common
		 * we have to go to the left neighbor, but if generation
		 * counter is 0 already, we know for sure, that there is
		 * no name with the same hash value
		 */
		/* FIXME: this work correctly only because hash value can
		 * not be 0. Btw, in case of Yura's hash it is probably
		 * possible, so, this is a bug
		 */
		return (NAME_NOT_FOUND);

	/*RFALSE(de->de_item_num,
	    "vs-7015: two diritems of the same directory in one node?");*/

	return (GOTO_PREVIOUS_ITEM);
}
Ejemplo n.º 24
0
/*
 * Common code for mount and mountroot
 */ 
static int
reiserfs_mountfs(struct vnode *devvp, struct mount *mp, struct thread *td)
{
	int error, old_format = 0;
	struct reiserfs_mount *rmp;
	struct reiserfs_sb_info *sbi;
	struct reiserfs_super_block *rs;
	struct cdev *dev;

	struct g_consumer *cp;
	struct bufobj *bo;

	//ronly = (mp->mnt_flag & MNT_RDONLY) != 0;

	dev = devvp->v_rdev;
	dev_ref(dev);
	DROP_GIANT();
	g_topology_lock();
	error = g_vfs_open(devvp, &cp, "reiserfs", /* read-only */ 0);
	g_topology_unlock();
	PICKUP_GIANT();
	VOP_UNLOCK(devvp, 0);
	if (error) {
		dev_rel(dev);
		return (error);
	}

	bo = &devvp->v_bufobj;
	bo->bo_private = cp;
	bo->bo_ops = g_vfs_bufops;

	if (devvp->v_rdev->si_iosize_max != 0)
		mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
	if (mp->mnt_iosize_max > MAXPHYS)
		mp->mnt_iosize_max = MAXPHYS;

	rmp = NULL;
	sbi = NULL;

	/* rmp contains any information about this specific mount */
	rmp = malloc(sizeof *rmp, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!rmp) {
		error = (ENOMEM);
		goto out;
	}
	sbi = malloc(sizeof *sbi, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!sbi) {
		error = (ENOMEM);
		goto out;
	}
	rmp->rm_reiserfs = sbi;
	rmp->rm_mountp   = mp;
	rmp->rm_devvp    = devvp;
	rmp->rm_dev      = dev;
	rmp->rm_bo       = &devvp->v_bufobj;
	rmp->rm_cp       = cp;

	/* Set default values for options: non-aggressive tails */
	REISERFS_SB(sbi)->s_mount_opt = (1 << REISERFS_SMALLTAIL);
	REISERFS_SB(sbi)->s_rd_only   = 1;
	REISERFS_SB(sbi)->s_devvp     = devvp;

	/* Read the super block */
	if ((error = read_super_block(rmp, REISERFS_OLD_DISK_OFFSET)) == 0) {
		/* The read process succeeded, it's an old format */
		old_format = 1;
	} else if ((error = read_super_block(rmp, REISERFS_DISK_OFFSET)) != 0) {
		reiserfs_log(LOG_ERR, "can not find a ReiserFS filesystem\n");
		goto out;
	}

	rs = SB_DISK_SUPER_BLOCK(sbi);

	/*
	 * Let's do basic sanity check to verify that underlying device is
	 * not smaller than the filesystem. If the check fails then abort and
	 * scream, because bad stuff will happen otherwise.
	 */
#if 0
	if (s->s_bdev && s->s_bdev->bd_inode &&
	    i_size_read(s->s_bdev->bd_inode) <
	    sb_block_count(rs) * sb_blocksize(rs)) {
		reiserfs_log(LOG_ERR,
		    "reiserfs: filesystem cannot be mounted because it is "
		    "bigger than the device.\n");
		reiserfs_log(LOG_ERR, "reiserfs: you may need to run fsck "
		    "rr may be you forgot to reboot after fdisk when it "
		    "told you to.\n");
		goto out;
	}
#endif

	/*
	 * XXX This is from the original Linux code, but why affecting 2 values
	 * to the same variable?
	 */
	sbi->s_mount_state = SB_REISERFS_STATE(sbi);
	sbi->s_mount_state = REISERFS_VALID_FS;

	if ((error = (old_format ?
	    read_old_bitmaps(rmp) : read_bitmaps(rmp)))) {
		reiserfs_log(LOG_ERR, "unable to read bitmap\n");
		goto out;
	}

	/* Make data=ordered the default */
	if (!reiserfs_data_log(sbi) && !reiserfs_data_ordered(sbi) &&
	    !reiserfs_data_writeback(sbi)) {
		REISERFS_SB(sbi)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED);
	}

	if (reiserfs_data_log(sbi)) {
		reiserfs_log(LOG_INFO, "using journaled data mode\n");
	} else if (reiserfs_data_ordered(sbi)) {
		reiserfs_log(LOG_INFO, "using ordered data mode\n");
	} else {
		reiserfs_log(LOG_INFO, "using writeback data mode\n");
	}

	/* TODO Not yet supported */
#if 0
	if(journal_init(sbi, jdev_name, old_format, commit_max_age)) {
		reiserfs_log(LOG_ERR, "unable to initialize journal space\n");
		goto out;
	} else {
		jinit_done = 1 ; /* once this is set, journal_release must
				    be called if we error out of the mount */
	}

	if (reread_meta_blocks(sbi)) {
		reiserfs_log(LOG_ERR,
		    "unable to reread meta blocks after journal init\n");
		goto out;
	}
#endif

	/* Define and initialize hash function */
	sbi->s_hash_function = hash_function(rmp);

	if (sbi->s_hash_function == NULL) {
		reiserfs_log(LOG_ERR, "couldn't determined hash function\n");
		error = (EINVAL);
		goto out;
	}

	if (is_reiserfs_3_5(rs) ||
	    (is_reiserfs_jr(rs) && SB_VERSION(sbi) == REISERFS_VERSION_1))
		bit_set(&(sbi->s_properties), REISERFS_3_5);
	else
		bit_set(&(sbi->s_properties), REISERFS_3_6);

	mp->mnt_data = rmp;
	mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
	MNT_ILOCK(mp);
	mp->mnt_flag |= MNT_LOCAL;
	mp->mnt_kern_flag |= MNTK_MPSAFE;
	MNT_IUNLOCK(mp);
#if defined(si_mountpoint)
	devvp->v_rdev->si_mountpoint = mp;
#endif

	return (0);

out:
	reiserfs_log(LOG_INFO, "*** error during mount ***\n");
	if (sbi) {
		if (SB_AP_BITMAP(sbi)) {
			int i;
			for (i = 0; i < SB_BMAP_NR(sbi); i++) {
				if (!SB_AP_BITMAP(sbi)[i].bp_data)
					break;
				free(SB_AP_BITMAP(sbi)[i].bp_data,
				    M_REISERFSMNT);
			}
			free(SB_AP_BITMAP(sbi), M_REISERFSMNT);
		}

		if (sbi->s_rs) {
			free(sbi->s_rs, M_REISERFSMNT);
			sbi->s_rs = NULL;
		}
	}

	if (cp != NULL) {
		DROP_GIANT();
		g_topology_lock();
		g_vfs_close(cp);
		g_topology_unlock();
		PICKUP_GIANT();
	}

	if (sbi)
		free(sbi, M_REISERFSMNT);
	if (rmp)
		free(rmp, M_REISERFSMNT);
	dev_rel(dev);
	return (error);
}
Ejemplo n.º 25
0
/*
 * Read the super block
 */
static int
read_super_block(struct reiserfs_mount *rmp, int offset)
{
	struct buf *bp;
	int error, bits;
	struct reiserfs_super_block *rs;
	struct reiserfs_sb_info *sbi;
	uint16_t fs_blocksize;

	if (offset == REISERFS_OLD_DISK_OFFSET) {
		reiserfs_log(LOG_DEBUG,
		    "reiserfs/super: read old format super block\n");
	} else {
		reiserfs_log(LOG_DEBUG,
		    "reiserfs/super: read new format super block\n");
	}

	/* Read the super block */
	if ((error = bread(rmp->rm_devvp, offset * btodb(REISERFS_BSIZE),
	    REISERFS_BSIZE, NOCRED, &bp)) != 0) {
		reiserfs_log(LOG_ERR, "can't read device\n");
		return (error);
	}

	/* Get it from the buffer data */
	rs = (struct reiserfs_super_block *)bp->b_data;
	if (!is_any_reiserfs_magic_string(rs)) {
		brelse(bp);
		return (EINVAL);
	}

	fs_blocksize = sb_blocksize(rs);
	brelse(bp);
	bp = NULL;

	if (fs_blocksize <= 0) {
		reiserfs_log(LOG_ERR, "unexpected null block size");
		return (EINVAL);
	}

	/* Read the super block (for double check)
	 * We can't read the same blkno with a different size: it causes
	 * panic() if INVARIANTS is set. So we keep REISERFS_BSIZE */
	if ((error = bread(rmp->rm_devvp,
	    offset * REISERFS_BSIZE / fs_blocksize * btodb(fs_blocksize),
	    REISERFS_BSIZE, NOCRED, &bp)) != 0) {
		reiserfs_log(LOG_ERR, "can't reread the super block\n");
		return (error);
	}

	rs = (struct reiserfs_super_block *)bp->b_data;
	if (sb_blocksize(rs) != fs_blocksize) {
		reiserfs_log(LOG_ERR, "unexpected block size "
		    "(found=%u, expected=%u)\n",
		    sb_blocksize(rs), fs_blocksize);
		brelse(bp);
		return (EINVAL);
	}

	reiserfs_log(LOG_DEBUG, "magic: `%s'\n", rs->s_v1.s_magic);
	reiserfs_log(LOG_DEBUG, "label: `%s'\n", rs->s_label);
	reiserfs_log(LOG_DEBUG, "block size:     %6d\n", sb_blocksize(rs));
	reiserfs_log(LOG_DEBUG, "block count:    %6u\n",
	    rs->s_v1.s_block_count);
	reiserfs_log(LOG_DEBUG, "bitmaps number: %6u\n",
	    rs->s_v1.s_bmap_nr);

	if (rs->s_v1.s_root_block == -1) {
		log(LOG_ERR,
		    "reiserfs: Unfinished reiserfsck --rebuild-tree run "
		    "detected. Please\n"
		    "run reiserfsck --rebuild-tree and wait for a "
		    "completion. If that\n"
		    "fails, get newer reiserfsprogs package");
		brelse(bp);
		return (EINVAL);
	}

	sbi = rmp->rm_reiserfs;
	sbi->s_blocksize = fs_blocksize;

	for (bits = 9, fs_blocksize >>= 9; fs_blocksize >>= 1; bits++)
		;
	sbi->s_blocksize_bits = bits;

	/* Copy the buffer and release it */
	sbi->s_rs = malloc(sizeof *rs, M_REISERFSMNT, M_WAITOK | M_ZERO);
	if (!sbi->s_rs) {
		reiserfs_log(LOG_ERR, "can not read the super block\n");
		brelse(bp);
		return (ENOMEM);
	}
	bcopy(rs, sbi->s_rs, sizeof(struct reiserfs_super_block));
	brelse(bp);

	if (is_reiserfs_jr(rs)) {
		if (sb_version(rs) == REISERFS_VERSION_2)
			reiserfs_log(LOG_INFO, "found reiserfs format \"3.6\""
			    " with non-standard journal");
		else if (sb_version(rs) == REISERFS_VERSION_1)
			reiserfs_log(LOG_INFO, "found reiserfs format \"3.5\""
			    " with non-standard journal");
		else {
			reiserfs_log(LOG_ERR, "found unknown "
			    "format \"%u\" of reiserfs with non-standard magic",
			    sb_version(rs));
			return (EINVAL);
		}
	} else {
		/*
		 * s_version of standard format may contain incorrect
		 * information, so we just look at the magic string
		 */
		reiserfs_log(LOG_INFO,
		    "found reiserfs format \"%s\" with standard journal\n",
		    is_reiserfs_3_5(rs) ? "3.5" : "3.6");
	}

	return (0);
}
Ejemplo n.º 26
0
int
reiserfs_lookup(struct vop_cachedlookup_args *ap)
{
	int error, retval;
	struct vnode *vdp         = ap->a_dvp;
	struct vnode **vpp        = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;

	int flags         = cnp->cn_flags;
	struct thread *td = cnp->cn_thread;
	struct cpu_key *saved_ino;

	struct vnode *vp;
	struct vnode *pdp;  /* Saved dp during symlink work */
	struct reiserfs_node *dp;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);

	char c = cnp->cn_nameptr[cnp->cn_namelen];
	cnp->cn_nameptr[cnp->cn_namelen] = '\0';
	reiserfs_log(LOG_DEBUG, "looking for `%s', %ld (%s)\n",
	    cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_pnbuf);
	cnp->cn_nameptr[cnp->cn_namelen] = c;

	vp = NULL;
	dp = VTOI(vdp);

	if (REISERFS_MAX_NAME(dp->i_reiserfs->s_blocksize) < cnp->cn_namelen)
		return (ENAMETOOLONG);

	reiserfs_log(LOG_DEBUG, "searching entry\n");
	de.de_gen_number_bit_string = 0;
	retval = reiserfs_find_entry(dp, cnp->cn_nameptr, cnp->cn_namelen,
	    &path_to_entry, &de);
	pathrelse(&path_to_entry);

	if (retval == NAME_FOUND) {
		reiserfs_log(LOG_DEBUG, "found\n");
	} else {
		reiserfs_log(LOG_DEBUG, "not found\n");
	}

	if (retval == NAME_FOUND) {
#if 0
		/* Hide the .reiserfs_priv directory */
		if (reiserfs_xattrs(dp->i_reiserfs) &&
		    !old_format_only(dp->i_reiserfs) &&
		    REISERFS_SB(dp->i_reiserfs)->priv_root &&
		    REISERFS_SB(dp->i_reiserfs)->priv_root->d_inode &&
		    de.de_objectid == le32toh(INODE_PKEY(REISERFS_SB(
		    dp->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
			return (EACCES);
		}
#endif

		reiserfs_log(LOG_DEBUG, "reading vnode\n");
		pdp = vdp;
		if (flags & ISDOTDOT) {
			saved_ino = (struct cpu_key *)&(de.de_dir_id);
			VOP_UNLOCK(pdp, 0);
			error = reiserfs_iget(vdp->v_mount,
			    saved_ino, &vp, td);
			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
			if (error != 0)
				return (error);
			*vpp = vp;
		} else if (de.de_objectid == dp->i_number &&
		    de.de_dir_id == dp->i_ino) {
			VREF(vdp); /* We want ourself, ie "." */
			*vpp = vdp;
		} else {
			if ((error = reiserfs_iget(vdp->v_mount,
			    (struct cpu_key *)&(de.de_dir_id), &vp, td)) != 0)
				return (error);
			*vpp = vp;
		}

		/*
		 * Propogate the priv_object flag so we know we're in the
		 * priv tree
		 */
		/*if (is_reiserfs_priv_object(dir))
			REISERFS_I(inode)->i_flags |= i_priv_object;*/
	} else {
		if (retval == IO_ERROR) {
			reiserfs_log(LOG_DEBUG, "IO error\n");
			return (EIO);
		}

		return (ENOENT);
	}

	/* Insert name into cache if appropriate. */
	if (cnp->cn_flags & MAKEENTRY)
		cache_enter(vdp, *vpp, cnp);

	reiserfs_log(LOG_DEBUG, "done\n");
	return (0);
}
Ejemplo n.º 27
0
int
reiserfs_readdir(struct vop_readdir_args  /* {
		struct vnode *a_vp;
		struct uio *a_uio;
		struct ucred *a_cred;
		int *a_eofflag;
		int *a_ncookies;
		u_long **a_cookies;
	} */*ap)
{
	int error = 0;
	struct dirent dstdp;
	struct uio *uio = ap->a_uio;

	off_t next_pos;
	struct buf *bp;
	struct item_head *ih;
	struct cpu_key pos_key;
	const struct key *rkey;
	struct reiserfs_node *ip;
	struct reiserfs_dir_entry de;
	INITIALIZE_PATH(path_to_entry);
	int entry_num, item_num, search_res;

	/* The NFS part */
	int ncookies = 0;
	u_long *cookies = NULL;

	/*
	 * Form key for search the next directory entry using f_pos field of
	 * file structure
	 */
	ip = VTOI(ap->a_vp);
	make_cpu_key(&pos_key,
	    ip, uio->uio_offset ? uio->uio_offset : DOT_OFFSET,
	    TYPE_DIRENTRY, 3);
	next_pos = cpu_key_k_offset(&pos_key);

	reiserfs_log(LOG_DEBUG, "listing entries for "
	    "(objectid=%d, dirid=%d)\n",
	    pos_key.on_disk_key.k_objectid, pos_key.on_disk_key.k_dir_id);
	reiserfs_log(LOG_DEBUG, "uio_offset = %jd, uio_resid = %d\n",
	    (intmax_t)uio->uio_offset, uio->uio_resid);

	if (ap->a_ncookies && ap->a_cookies) {
		cookies = (u_long *)malloc(
		    uio->uio_resid / 16 * sizeof(u_long),
		    M_REISERFSCOOKIES, M_WAITOK);
	}

	while (1) {
		//research:
		/*
		 * Search the directory item, containing entry with
		 * specified key
		 */
		reiserfs_log(LOG_DEBUG, "search directory to read\n");
		search_res = search_by_entry_key(ip->i_reiserfs, &pos_key,
		    &path_to_entry, &de);
		if (search_res == IO_ERROR) {
			error = EIO;
			goto out;
		}

		entry_num = de.de_entry_num;
		item_num  = de.de_item_num;
		bp = de.de_bp;
		ih = de.de_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(bp, ih) +
			    entry_num;

			if (ap->a_ncookies == NULL) {
				cookies = NULL;
			} else {
				//ncookies = 
			}

			reiserfs_log(LOG_DEBUG,
			    "walking through directory entries\n");
			for (; entry_num < I_ENTRY_COUNT(ih);
			    entry_num++, deh++) {
				int d_namlen;
				char *d_name;
				off_t d_off;
				ino_t d_ino;

				if (!de_visible(deh)) {
					/* It is hidden entry */
					continue;
				}

				d_namlen = entry_length(bp, ih, entry_num);
				d_name   = B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh);
				if (!d_name[d_namlen - 1])
					d_namlen = strlen(d_name);
				reiserfs_log(LOG_DEBUG, "  - `%s' (len=%d)\n",
				    d_name, d_namlen);

				if (d_namlen > REISERFS_MAX_NAME(
				    ip->i_reiserfs->s_blocksize)) {
					/* Too big to send back to VFS */
					continue;
				}

#if 0
				/* Ignore the .reiserfs_priv entry */
				if (reiserfs_xattrs(ip->i_reiserfs) &&
				    !old_format_only(ip->i_reiserfs) &&
				    filp->f_dentry == ip->i_reiserfs->s_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root &&
				    REISERFS_SB(ip->i_reiserfs)->priv_root->d_inode &&
				    deh_objectid(deh) ==
				    le32toh(INODE_PKEY(REISERFS_SB(
				    ip->i_reiserfs)->priv_root->d_inode)->k_objectid)) {
					continue;
				}
#endif

				d_off = deh_offset(deh);
				d_ino = deh_objectid(deh);
				uio->uio_offset = d_off;

				/* Copy to user land */
				dstdp.d_fileno = d_ino;
				dstdp.d_type   = DT_UNKNOWN;
				dstdp.d_namlen = d_namlen;
				dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
				bcopy(d_name, dstdp.d_name, dstdp.d_namlen);
				bzero(dstdp.d_name + dstdp.d_namlen,
				    dstdp.d_reclen -
				    offsetof(struct dirent, d_name) -
				    dstdp.d_namlen);

				if (d_namlen > 0) {
					if (dstdp.d_reclen <= uio->uio_resid) {
						reiserfs_log(LOG_DEBUG, "     copying to user land\n");
						error = uiomove(&dstdp,
						    dstdp.d_reclen, uio);
						if (error)
							goto end;
						if (cookies != NULL) {
							cookies[ncookies] =
							    d_off;
							ncookies++;
						}
					} else
						break;
				} else {
					error = EIO;
					break;
				}

				next_pos = deh_offset(deh) + 1;
			}
			reiserfs_log(LOG_DEBUG, "...done\n");
		}

		reiserfs_log(LOG_DEBUG, "checking item num (%d == %d ?)\n",
		    item_num, B_NR_ITEMS(bp) - 1);
		if (item_num != B_NR_ITEMS(bp) - 1) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/*
		 * Item we went through is last item of node. Using right
		 * delimiting key check is it directory end
		 */
		reiserfs_log(LOG_DEBUG, "get right key\n");
		rkey = get_rkey(&path_to_entry, ip->i_reiserfs);
		reiserfs_log(LOG_DEBUG, "right key = (objectid=%d, dirid=%d)\n",
		    rkey->k_objectid, rkey->k_dir_id);

		reiserfs_log(LOG_DEBUG, "compare it to MIN_KEY\n");
		reiserfs_log(LOG_DEBUG, "MIN KEY = (objectid=%d, dirid=%d)\n",
		    MIN_KEY.k_objectid, MIN_KEY.k_dir_id);
		if (comp_le_keys(rkey, &MIN_KEY) == 0) {
			/* Set pos_key to key, that is the smallest and greater
			 * that key of the last entry in the item */
			reiserfs_log(LOG_DEBUG, "continuing on the right\n");
			set_cpu_key_k_offset(&pos_key, next_pos);
			continue;
		}

		reiserfs_log(LOG_DEBUG, "compare it to pos_key\n");
		reiserfs_log(LOG_DEBUG, "pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
		if (COMP_SHORT_KEYS(rkey, &pos_key)) {
			/* End of directory has been reached */
			reiserfs_log(LOG_DEBUG, "end reached (right)\n");
			if (ap->a_eofflag)
				*ap->a_eofflag = 1;
			goto end;
		}

		/* Directory continues in the right neighboring block */
		reiserfs_log(LOG_DEBUG, "continuing with a new offset\n");
		set_cpu_key_k_offset(&pos_key,
		    le_key_k_offset(KEY_FORMAT_3_5, rkey));
		reiserfs_log(LOG_DEBUG,
		    "new pos key = (objectid=%d, dirid=%d)\n",
		    pos_key.on_disk_key.k_objectid,
		    pos_key.on_disk_key.k_dir_id);
	}

end:
	uio->uio_offset = next_pos;
	pathrelse(&path_to_entry);
	reiserfs_check_path(&path_to_entry);
out:
	if (error && cookies != NULL) {
		free(cookies, M_REISERFSCOOKIES);
	} else if (ap->a_ncookies != NULL && ap->a_cookies != NULL) {
		*ap->a_ncookies = ncookies;
		*ap->a_cookies  = cookies;
	}
	return (error);
}
Ejemplo n.º 28
0
/*
 * Mount system call
 */
static int
reiserfs_mount(struct mount *mp)
{
	size_t size;
	int error, len;
	accmode_t accmode;
	char *path, *fspec;
	struct vnode *devvp;
	struct vfsoptlist *opts;
	struct reiserfs_mount *rmp;
	struct reiserfs_sb_info *sbi;
	struct nameidata nd, *ndp = &nd;
	struct thread *td;

	td = curthread;
	if (!(mp->mnt_flag & MNT_RDONLY))
		return EROFS;

	/* Get the new options passed to mount */
	opts = mp->mnt_optnew;

	/* `fspath' contains the mount point (eg. /mnt/linux); REQUIRED */
	vfs_getopt(opts, "fspath", (void **)&path, NULL);
	reiserfs_log(LOG_INFO, "mount point is `%s'\n", path);

	/* `from' contains the device name (eg. /dev/ad0s1); REQUIRED */
	fspec = NULL;
	error = vfs_getopt(opts, "from", (void **)&fspec, &len);
	if (!error && fspec[len - 1] != '\0')
		return (EINVAL);
	reiserfs_log(LOG_INFO, "device is `%s'\n", fspec);

	/* Handle MNT_UPDATE (mp->mnt_flag) */
	if (mp->mnt_flag & MNT_UPDATE) {
		/* For now, only NFS export is supported. */
		if (vfs_flagopt(opts, "export", NULL, 0))
			return (0);
	}

	/* Not an update, or updating the name: look up the name
	 * and verify that it refers to a sensible disk device. */
	if (fspec == NULL)
		return (EINVAL);

	NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td);
	if ((error = namei(ndp)) != 0)
		return (error);
	NDFREE(ndp, NDF_ONLY_PNBUF);
	devvp = ndp->ni_vp;

	if (!vn_isdisk(devvp, &error)) {
		vput(devvp);
		return (error);
	}

	/* If mount by non-root, then verify that user has necessary
	 * permissions on the device. */
	accmode = VREAD;
	if ((mp->mnt_flag & MNT_RDONLY) == 0)
		accmode |= VWRITE;
	error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
	if (error)
		error = priv_check(td, PRIV_VFS_MOUNT_PERM);
	if (error) {
		vput(devvp);
		return (error);
	}

	if ((mp->mnt_flag & MNT_UPDATE) == 0) {
		error = reiserfs_mountfs(devvp, mp, td);
	} else {
		/* TODO Handle MNT_UPDATE */
		vput(devvp);
		return (EOPNOTSUPP);
	}

	if (error) {
		vrele(devvp);
		return (error);
	}

	rmp = VFSTOREISERFS(mp);
	sbi = rmp->rm_reiserfs;

	/*
	 * Note that this strncpy() is ok because of a check at the start
	 * of reiserfs_mount().
	 */
	reiserfs_log(LOG_DEBUG, "prepare statfs data\n");
	(void)copystr(fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
	(void)reiserfs_statfs(mp, &mp->mnt_stat);

	reiserfs_log(LOG_DEBUG, "done\n");
	return (0);
}
Ejemplo n.º 29
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 both
 * have the same value - we ask user to send report to the mailing list
 */
uint32_t find_hash_out(struct reiserfs_mount *rmp)
{
	int retval;
	struct cpu_key key;
	INITIALIZE_PATH(path);
	struct reiserfs_node *ip;
	struct reiserfs_sb_info *sbi;
	struct reiserfs_dir_entry de;
	uint32_t hash = DEFAULT_HASH;

	get_root_node(rmp, &ip);
	if (!ip)
		return (UNSET_HASH);

	sbi = rmp->rm_reiserfs;

	do {
		uint32_t teahash, r5hash, yurahash;

		reiserfs_log(LOG_DEBUG, "make_cpu_key\n");
		make_cpu_key(&key, ip, ~0, TYPE_DIRENTRY, 3);
		reiserfs_log(LOG_DEBUG, "search_by_entry_key for "
		    "key(objectid=%d,dirid=%d)\n",
		    key.on_disk_key.k_objectid, key.on_disk_key.k_dir_id);
		retval = search_by_entry_key(sbi, &key, &path, &de);
		if (retval == IO_ERROR) {
			pathrelse(&path);
			return (UNSET_HASH);
		}
		if (retval == NAME_NOT_FOUND)
			de.de_entry_num--;

		reiserfs_log(LOG_DEBUG, "name found\n");

		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(sbi)) {
				hash = YURA_HASH;
			}
			reiserfs_log(LOG_DEBUG,
			    "FS seems to be empty, autodetect "
			    "is using the default hash");
			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_log(LOG_ERR,
			    "unable to automatically detect hash "
			    "function. Please mount with -o "
			    "hash={tea,rupasov,r5}");
			hash = UNSET_HASH;
			break;
		}

		if (GET_HASH_VALUE(
		    deh_offset(&(de.de_deh[de.de_entry_num]))) == yurahash) {
			reiserfs_log(LOG_DEBUG, "detected YURA hash\n");
			hash = YURA_HASH;
		} else if (GET_HASH_VALUE(
		    deh_offset(&(de.de_deh[de.de_entry_num]))) == teahash) {
			reiserfs_log(LOG_DEBUG, "detected TEA hash\n");
			hash = TEA_HASH;
		} else if (GET_HASH_VALUE(
		    deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash) {
			reiserfs_log(LOG_DEBUG, "detected R5 hash\n");
			hash = R5_HASH;
		} else {
			reiserfs_log(LOG_WARNING, "unrecognised hash function");
			hash = UNSET_HASH;
		}
	} while (0);

	pathrelse(&path);
	return (hash);
}