コード例 #1
0
ファイル: item_ops.c プロジェクト: niubl/camera_project
static void sd_print_item (struct item_head * ih, char * item)
{
    printk ("\tmode | size | nlinks | first direct | mtime\n");
    if (stat_data_v1 (ih)) {
      	struct stat_data_v1 * sd = (struct stat_data_v1 *)item;

	printk ("\t0%-6o | %6u | %2u | %d | %s\n", sd_v1_mode(sd),
                sd_v1_size(sd), sd_v1_nlink(sd), sd_v1_first_direct_byte(sd),
                print_time( sd_v1_mtime(sd) ) );
    } else {
	struct stat_data * sd = (struct stat_data *)item;

	printk ("\t0%-6o | %6Lu | %2u | %d | %s\n", sd_v2_mode(sd),
            (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd),
            sd_v2_rdev(sd), print_time(sd_v2_mtime(sd)));
    }
}
コード例 #2
0
ファイル: pass0.c プロジェクト: BackupTheBerlios/wl530g-svn
/* FIXME: we can improve fixing of broken keys: we can ssfe direct items which
   go after stat data and have broken keys */
static void pass0_correct_leaf (reiserfs_filsys_t fs,
				struct buffer_head * bh)
{
    int i, j;
    struct item_head * ih;
    __u32 * ind_item;
    unsigned long unfm_ptr;
    int dirty = 0;

 start_again:

    ih = B_N_PITEM_HEAD (bh, 0);
    for (i = 0; i < node_item_number (bh); i ++, ih ++) {
	if (ih->ih_key.k_dir_id == 0 || ih->ih_key.k_objectid == 0) {
	    /* sometimes stat datas get k_objectid==0 or k_dir_id==0 */
	    if (i == (node_item_number (bh) - 1)) {
		/* */
		if (i == 0) {
		    fsck_log ("block %lu: item %d: (%H) is alone in the block\n",
			      bh->b_blocknr, i, ih);
		    return;
		}
		/* delete last item */
		delete_item (fs, bh, i - 1);
		return;
	    }

	    /* there is next item: if it is not stat data - take its k_dir_id
               and k_objectid. if key order will be still wrong - the changed
               item will be deleted */
	    if (!is_stat_data_ih (ih + 1)) {
		fsck_log ("block %lu: item %d: (%H) fixed to ", bh->b_blocknr, i, ih);
		ih->ih_key.k_dir_id = (ih + 1)->ih_key.k_dir_id;
		ih->ih_key.k_objectid = (ih + 1)->ih_key.k_objectid;
		set_offset (KEY_FORMAT_1, &ih->ih_key, 0);
		set_type (KEY_FORMAT_1, &ih->ih_key, TYPE_STAT_DATA);
		fsck_log ("(%H)\n", ih);
		dirty = 1;
	    } else if (i == 0) {
		delete_item (fs, bh, i);
		goto start_again;
	    }
	}

	/* this recovers corruptions like the below: 
	   1774 1732 0 0
	   116262638 1732 1 3
	   1774 1736 0 0 */
	if (i && is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) {
	    if (ih->ih_key.k_objectid != (ih - 1)->ih_key.k_objectid ||
		ih->ih_key.k_dir_id != (ih - 1)->ih_key.k_dir_id ||
		get_offset (&ih->ih_key) != 1) {
		if (is_direntry_ih (ih)) {
		    fsck_log ("block %lu: item %d: no \".\" entry found in "
			      "the first item of a directory\n", bh->b_blocknr, i);
		} else {
		    fsck_log ("block %lu: item %d: (%H) fixed to ", 
			  bh->b_blocknr, i, ih);
		    ih->ih_key.k_dir_id = (ih - 1)->ih_key.k_dir_id;
		    ih->ih_key.k_objectid = (ih - 1)->ih_key.k_objectid;
		    
		    if (ih_item_len (ih - 1) == SD_SIZE) {
			/* stat data is new, therefore this item is new too */
			set_offset (KEY_FORMAT_2, &(ih->ih_key), 1);
			if (ih_entry_count (ih) != 0xffff)
			    set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_INDIRECT);
			else
			    set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_DIRECT);
			set_ih_key_format (ih, KEY_FORMAT_2);
		    } else {
			/* stat data is old, therefore this item is old too */
			set_offset (KEY_FORMAT_1, &(ih->ih_key), 1);
			if (ih_entry_count (ih) != 0xffff)
			    set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_INDIRECT);
			else
			    set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_DIRECT);
			set_ih_key_format (ih, KEY_FORMAT_1);
		    }
		    fsck_log ("%H\n", ih);
		    dirty = 1;
		}
	    }
	}

	/* FIXME: corruptions like:
	   56702 66802 1 2
	   56702 65536 0 0
	   56702 66803 1 2
	   do not get recovered (both last items will be deleted) */
	/* delete item if it is not in correct order of object items */
	if (i && not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key) &&
	    !is_stat_data_ih (ih)) {
	    fsck_log ("block %lu: item %d: %H follows non stat item %H - deleted\n",
		      bh->b_blocknr, i, ih, ih - 1);
	    delete_item (fs, bh, i);
	    goto start_again;
	}

	if (i &&  comp_keys (&(ih - 1)->ih_key, &ih->ih_key) != -1) {
	    /* previous item has key not smaller than the key of currect item */
	    if (is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) {
		/* fix key of stat data such as if it was stat data of that item */
		fsck_log ("pass0: block %lu: %d-th item %k is out of order, made a stat data of %d-th (%k)\n",
			  bh->b_blocknr, i - 1, &(ih - 1)->ih_key, i, &ih->ih_key);
		(ih - 1)->ih_key.k_dir_id = ih->ih_key.k_dir_id;
		(ih - 1)->ih_key.k_objectid = ih->ih_key.k_objectid;
		set_offset (KEY_FORMAT_1, &(ih - 1)->ih_key, 0);
		set_type (KEY_FORMAT_1, &(ih - 1)->ih_key, TYPE_STAT_DATA);
		dirty = 1;
	    } else {
		/* ok, we have to delete one of these two - decide which one */
		int retval;

		/* something will be deleted */
		dirty = 1;
		retval = upper_correct (bh, ih - 1, i - 1);
		switch (retval) {
		case 0:
		    /* delete upper item */
		    fsck_log ("pass0: block %lu: %d-th (upper) item (%k) is out of order, deleted\n",
			      bh->b_blocknr, i - 1, &(ih - 1)->ih_key);
		    delete_item (fs, bh, i - 1);
		    goto start_again;

		case 1:
		    /* delete lower item */
		    fsck_log ("pass0: block %lu: %d-th (lower) item (%k) is out of order, deleted\n",
			      bh->b_blocknr, i, &ih->ih_key);
		    delete_item (fs, bh, i);
		    goto start_again;

		default:
		    /* upper item was the first item of a node */
		}

		retval = lower_correct (bh, ih, i);
		switch (retval) {
		case 0:
		    /* delete lower item */
		    fsck_log ("pass0: block %lu: %d-th (lower) item (%k) is out of order, deleted\n",
			      bh->b_blocknr, i, &ih->ih_key);
		    delete_item (fs, bh, i);
		    goto start_again;

		case 1:
		    /* delete upper item */
		    fsck_log ("pass0: block %lu: %d-th (upper) item (%k) is out of order, deleted\n",
			      bh->b_blocknr, i - 1, &(ih - 1)->ih_key);
		    delete_item (fs, bh, i - 1);
		    goto start_again;

		default:
		    /* there wer only two items in a node, so we could not
                       decide what to delete, go and ask user */
		}
		fsck_log ("pass0: which of these items looks better (other will be deleted)?\n"
			  "%H\n%H\n", ih - 1, ih);
		if (fsck_user_confirmed (fs, "1 or 2?", "1\n", 1))
		    delete_item (fs, bh, i - 1);
		else
		    delete_item (fs, bh, i);
		goto start_again;
	    }
	}

	if (is_stat_data_ih (ih) && (ih_item_len (ih) != SD_SIZE &&
				     ih_item_len (ih) != SD_V1_SIZE)) {
	    fsck_log ("pass0: block %lu, stat data of wrong length %H - deleted\n",
		      bh, ih);
	    delete_item (fs, bh, i);
	    goto start_again;
	}

	dirty += correct_key_format (ih);

	if (is_stat_data_ih (ih)) {
	    ;/*correct_stat_data (fs, bh, i);*/
	}

	if (is_direntry_ih (ih)) {
	    verify_directory_item (fs, bh, i);
	    continue;
	}

	if (!is_indirect_ih (ih))
	    continue;
	
	ind_item = (__u32 *)B_I_PITEM (bh, ih);
	for (j = 0; j < I_UNFM_NUM (ih); j ++) {
	    unfm_ptr = le32_to_cpu (ind_item [j]);
	    if (!unfm_ptr)
		continue;
	    
	    if (fsck_mode (fs) == FSCK_ZERO_FILES) {
		/* FIXME: this is temporary mode of fsck */
		ind_item [j] = 0;
		reiserfs_bitmap_clear_bit (fsck_new_bitmap(fs), unfm_ptr);
		tmp_zeroed ++;
		dirty = 1;
		continue;
	    }

	    if (not_data_block (fs, unfm_ptr) || /* journal area or bitmap or super block */
		unfm_ptr >= SB_BLOCK_COUNT (fs)) {/* garbage in pointer */

		stats (fs)->wrong_pointers ++;
		/*
		fsck_log ("pass0: %d-th pointer (%lu) in item %k (leaf block %lu) is wrong\n",
			  j, unfm_ptr, &ih->ih_key, bh->b_blocknr);
		*/
		ind_item [j] = 0;
		dirty = 1;
		continue;
	    }
#if 0
	    if (!was_block_used (unfm_ptr)) {
	      /* this will get to a pool of allocable blocks */
	      ind_item [j] = 0;
	      dirty = 1;
	      stat_wrong_pointer_found (fs);
	      continue;
	    }
#endif
	    /* mark block in bitmaps of unformatted nodes */
	    register_unfm (unfm_ptr);
	}
    }

    /* mark all objectids in use */
    ih = B_N_PITEM_HEAD (bh, 0);
    for (i = 0; i < node_item_number (bh); i ++, ih ++) {
	mark_objectid_really_used (proper_id_map (fs), le32_to_cpu (ih->ih_key.k_dir_id));
	mark_objectid_really_used (proper_id_map (fs), le32_to_cpu (ih->ih_key.k_objectid));
    }

    if (node_item_number (bh) < 1) {
	/* pass 1 will skip this */
	stats(fs)->all_contents_removed ++;
	fsck_log ("pass0: block %lu got all items deleted\n",
		  bh->b_blocknr);
    } else {
	/* pass1 will use this bitmap */
	pass0_mark_leaf (bh->b_blocknr);

    }
    if (dirty) {
	stats(fs)->leaves_corrected ++;
	mark_buffer_dirty (bh);
    }
}


static int is_bad_sd (struct item_head * ih, char * item)
{
    struct stat_data * sd = (struct stat_data *)item;

    if (le32_to_cpu(ih->ih_key.u.k_offset_v1.k_offset) || le32_to_cpu(ih->ih_key.u.k_offset_v1.k_uniqueness)) {
	reiserfs_warning (stderr, "Bad SD? %H\n", ih);
	return 1;
    }

    if (ih_item_len (ih) == SD_V1_SIZE) {
	/* looks like old stat data */
	if (ih_key_format (ih) != KEY_FORMAT_1)
	    fsck_log ("item %H has wrong format\n", ih);
	return 0;
    }

    if (!S_ISDIR (sd_v2_mode(sd)) && !S_ISREG(sd_v2_mode(sd)) &&
	!S_ISCHR (sd_v2_mode(sd)) && !S_ISBLK(sd_v2_mode(sd)) &&
	!S_ISLNK (sd_v2_mode(sd)) && !S_ISFIFO(sd_v2_mode(sd)) &&
	!S_ISSOCK(sd_v2_mode(sd))) {	
	/*fsck_log ("file %k unexpected mode encountered 0%o\n", &ih->ih_key, sd_v2_mode(sd))*/;
    }
    return 0;
}


int is_bad_directory (struct item_head * ih, char * item, int dev, int blocksize)
{
    int i;
    char * name;
    int namelen, entrylen;
    struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item;
    __u32 prev_offset = 0;
    __u16 prev_location = ih_item_len (ih);
    int min_entry_size = 1;/* we have no way to understand whether the
                              filesystem were created in 3.6 format or
                              converted to it. So, we assume that minimal name
                              length is 1 */

    if (ih_item_len (ih) / (DEH_SIZE + min_entry_size) < ih_entry_count (ih))
	/* entry count is too big */
	return 1;

    for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
	entrylen = entry_length(ih, deh, i);
	if (entrylen > REISERFS_MAX_NAME_LEN (blocksize)) {
	    return 1;
	}
	if (deh_offset (deh) <= prev_offset) {
	    return 1;
	}
	prev_offset = deh_offset (deh);

	if (deh_location(deh) + entrylen != prev_location) {
	    return 1;
	}
	prev_location = deh_location (deh);

	namelen = name_length (ih, deh, i);
	name = name_in_entry (deh, i);
	if (!is_properly_hashed (fs, name, namelen, deh_offset (deh))) {
	    return 1;
	}
    }
    return 0;
}


/* change incorrect block adresses by 0. Do not consider such item as incorrect */
static int is_bad_indirect (struct item_head * ih, char * item, int dev, int blocksize)
{
    int i;
    int bad = 0;
    int blocks;

    if (ih_item_len(ih) % UNFM_P_SIZE) {
	fsck_log ("is_bad_indirect: indirect item of %H of invalid length\n", ih);
	return 1;
    }

    blocks = SB_BLOCK_COUNT (fs);
  
    for (i = 0; i < I_UNFM_NUM (ih); i ++) {
	__u32 * ind = (__u32 *)item;

	if (le32_to_cpu (ind[i]) >= blocks) {
	    bad ++;
	    fsck_log ("is_bad_indirect: %d-th pointer of item %H looks bad (%lu)\n",
		      i, ih, le32_to_cpu (ind [i]));
	    continue;
	}
    }
    return bad;
}