Example #1
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);
}
Example #2
0
/* returns 1 if buf looks like an internal node, 0 otherwise */
static int is_internal(char *buf, int blocksize, struct buffer_head *bh)
{
	struct block_head *blkh;
	int nr;
	int used_space;

	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_warning(NULL, "reiserfs-5087",
				 "this should be caught earlier");
		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_warning(NULL, "reiserfs-5088",
				 "number of key seems wrong: %z", bh);
		return 0;
	}

	used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
	if (used_space != blocksize - blkh_free_space(blkh)) {
		reiserfs_warning(NULL, "reiserfs-5089",
				 "free space seems wrong: %z", bh);
		return 0;
	}
	// one may imagine much more checks
	return 1;
}
Example #3
0
/* Read in the node at the current path and depth into the node cache.
 * You must set INFO->blocks[depth] before.
 */
static char *
read_tree_node( __u32 blockNr, __u16 depth )
{
     char *cache = CACHE(depth);
     int num_cached = INFO->cached_slots;
     errnum = 0;

     if ( depth < num_cached )
     {
	  /* This is the cached part of the path.
	     Check if same block is needed. */
	  if ( blockNr == INFO->blocks[depth] )
	       return cache;
     }
     else
	  cache = CACHE(num_cached);

     DEBUG_F( "  next read_in: block=%u (depth=%u)\n", blockNr, depth );

     if ( !block_read( blockNr, 0, INFO->blocksize, cache ) )
     {
	  DEBUG_F( "block_read failed\n" );
	  return 0;
     }

     DEBUG_F( "FOUND: blk_level=%u, blk_nr_item=%u, blk_free_space=%u\n",
	      blkh_level(BLOCKHEAD(cache)),
	      blkh_nr_item(BLOCKHEAD(cache)),
	      le16_to_cpu(BLOCKHEAD(cache)->blk_free_space) );

     /* Make sure it has the right node level */
     if ( blkh_level(BLOCKHEAD(cache)) != depth )
     {
	  DEBUG_F( "depth = %u != %u\n", blkh_level(BLOCKHEAD(cache)), depth );
	  DEBUG_LEAVE(FILE_ERR_BAD_FSYS);
	  errnum = FILE_ERR_BAD_FSYS;
	  return 0;
     }

     INFO->blocks[depth] = blockNr;
     return cache;
}
Example #4
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;
}
Example #5
0
static int is_leaf(char *buf, int blocksize, struct buffer_head *bh)
{
	struct block_head *blkh;
	struct item_head *ih;
	int used_space;
	int prev_location;
	int i;
	int nr;

	blkh = (struct block_head *)buf;
	if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
		reiserfs_warning(NULL, "reiserfs-5080",
				 "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_warning(NULL, "reiserfs-5081",
				 "nr_item seems wrong: %z", bh);
		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_warning(NULL, "reiserfs-5082",
				 "free space seems wrong: %z", bh);
		return 0;
	}
	// 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_warning(NULL, "reiserfs-5083",
					 "wrong item type for item %h",
					 ih);
			return 0;
		}
		if (ih_location(ih) >= blocksize
		    || ih_location(ih) < IH_SIZE * nr) {
			reiserfs_warning(NULL, "reiserfs-5084",
					 "item location seems wrong: %h",
					 ih);
			return 0;
		}
		if (ih_item_len(ih) < 1
		    || ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
			reiserfs_warning(NULL, "reiserfs-5085",
					 "item length seems wrong: %h",
					 ih);
			return 0;
		}
		if (prev_location - ih_location(ih) != ih_item_len(ih)) {
			reiserfs_warning(NULL, "reiserfs-5086",
					 "item location seems wrong "
					 "(second one): %h", ih);
			return 0;
		}
		prev_location = ih_location(ih);
	}

	// one may imagine much more checks
	return 1;
}
Example #6
0
/* check filesystem types and read superblock into memory buffer */
static int
reiserfs_read_super( void )
{
     struct reiserfs_super_block super;
     __u64 superblock = REISERFS_SUPERBLOCK_BLOCK;

     if (read_disk_block(INFO->file, superblock, 0, sizeof(super), &super) != sizeof(super)) {
	  DEBUG_F("read_disk_block failed!\n");
	  return 0;
     }

     DEBUG_F( "Found super->magic: \"%s\"\n", super.s_magic );

     if( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
	 strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
     {
	  /* Try old super block position */
	  superblock = REISERFS_OLD_SUPERBLOCK_BLOCK;

	  if (read_disk_block( INFO->file, superblock, 0, sizeof (super),  &super ) != sizeof(super)) {
	       DEBUG_F("read_disk_block failed!\n");
	       return 0;
	  }

	  if ( strcmp( REISER2FS_SUPER_MAGIC_STRING, super.s_magic ) != 0 &&
	       strcmp( REISERFS_SUPER_MAGIC_STRING, super.s_magic ) != 0 )
	  {
	       /* pre journaling super block - untested */
	       if ( strcmp( REISERFS_SUPER_MAGIC_STRING,
			    (char *) ((__u32) &super + 20 ) ) != 0 )
		    return 0;

	       super.s_blocksize = cpu_to_le16(REISERFS_OLD_BLOCKSIZE);
	       super.s_journal_block = 0;
	       super.s_version = 0;
	  }
     }

     DEBUG_F( "ReiserFS superblock data:\n" );
     DEBUG_F( "Block count: %u\n", le32_to_cpu(super.s_block_count) )
	  DEBUG_F( "Free blocks: %u\n", le32_to_cpu(super.s_free_blocks) );
     DEBUG_F( "Journal block: %u\n", le32_to_cpu(super.s_journal_block) );
     DEBUG_F( "Journal size (in blocks): %u\n",
	      le32_to_cpu(super.s_orig_journal_size) );
     DEBUG_F( "Root block: %u\n\n", le32_to_cpu(super.s_root_block) );


     INFO->version = le16_to_cpu(super.s_version);
     INFO->blocksize = le16_to_cpu(super.s_blocksize);
     INFO->blocksize_shift = log2( INFO->blocksize );

     INFO->journal_block = le32_to_cpu(super.s_journal_block);
     INFO->journal_block_count = le32_to_cpu(super.s_orig_journal_size);

     INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->blocksize_shift) - 1;

     /* At this point, we've found a valid superblock. If we run into problems
      * mounting the FS, the user should probably know. */

     /* A few sanity checks ... */
     if ( INFO->version > REISERFS_MAX_SUPPORTED_VERSION )
     {
	  prom_printf( "ReiserFS: Unsupported version field: %u\n",
		       INFO->version );
	  return 0;
     }

     if ( INFO->blocksize < FSYSREISER_MIN_BLOCKSIZE
	  || INFO->blocksize > FSYSREISER_MAX_BLOCKSIZE )
     {
	  prom_printf( "ReiserFS: Unsupported block size: %u\n",
		       INFO->blocksize );
	  return 0;
     }

     /* Setup the journal.. */
     if ( INFO->journal_block != 0 )
     {
	  if ( !is_power_of_two( INFO->journal_block_count ) )
	  {
	       prom_printf( "ReiserFS: Unsupported journal size, "
			    "not a power of 2: %u\n",
			    INFO->journal_block_count );
	       return 0;
	  }

	  journal_init();
	  /* Read in super block again, maybe it is in the journal */
	  block_read( superblock, 0, sizeof (struct reiserfs_super_block),
		      (char *) &super );
     }

     /* Read in the root block */
     if ( !block_read( le32_to_cpu(super.s_root_block), 0,
		       INFO->blocksize, ROOT ) )
     {
	  prom_printf( "ReiserFS: Failed to read in root block\n" );
	  return 0;
     }

     /* The root node is always the "deepest", so we can
	determine the hieght of the tree using it. */
     INFO->tree_depth = blkh_level(BLOCKHEAD(ROOT));


     DEBUG_F( "root read_in: block=%u, depth=%u\n",
	      le32_to_cpu(super.s_root_block), INFO->tree_depth );

     if ( INFO->tree_depth >= REISERFS_MAX_TREE_HEIGHT )
     {
	  prom_printf( "ReiserFS: Unsupported tree depth (too deep): %u\n",
		       INFO->tree_depth );
	  return 0;
     }

     if ( INFO->tree_depth == BLKH_LEVEL_LEAF )
     {
	  /* There is only one node in the whole filesystem, which is
	     simultanously leaf and root */
	  memcpy( LEAF, ROOT, INFO->blocksize );
     }
     return 1;
}