Beispiel #1
0
errcode_t ocfs2_block_iterate(ocfs2_filesys *fs,
			      uint64_t blkno,
			      int flags,
			      int (*func)(ocfs2_filesys *fs,
					  uint64_t blkno,
					  uint64_t bcount,
					  uint16_t ext_flags,
					  void *priv_data),
			      void *priv_data)
{
	struct ocfs2_dinode *inode;
	errcode_t ret;
	char *buf;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto out_buf;

	inode = (struct ocfs2_dinode *)buf;

	ret = ocfs2_block_iterate_inode(fs, inode, flags, func, priv_data);

out_buf:
	ocfs2_free(&buf);
	return ret;
}
Beispiel #2
0
errcode_t o2fsck_type_from_dinode(o2fsck_state *ost, uint64_t ino,
                                  uint8_t *type)
{
    char *buf = NULL;
    errcode_t ret;
    struct ocfs2_dinode *dinode;
    const char *whoami = __FUNCTION__;

    *type = 0;

    ret = ocfs2_malloc_block(ost->ost_fs->fs_io, &buf);
    if (ret) {
        com_err(whoami, ret, "while allocating an inode buffer to "
                "read and discover the type of inode %"PRIu64, ino);
        goto out;
    }

    ret = ocfs2_read_inode(ost->ost_fs, ino, buf);
    if (ret) {
        com_err(whoami, ret, "while reading inode %"PRIu64" to "
                "discover its file type", ino);
        goto out;
    }

    dinode = (struct ocfs2_dinode *)buf;
    *type = ocfs2_type_by_mode[(dinode->i_mode & S_IFMT)>>S_SHIFT];

out:
    if (buf)
        ocfs2_free(&buf);
    return ret;
}
Beispiel #3
0
void mess_up_inode_alloc(ocfs2_filesys *fs, enum fsck_type type,
			 uint16_t slotnum)
{
	errcode_t ret;
	uint64_t tmpblkno;
	char *buf = NULL;
	struct ocfs2_dinode *di;

	ret = ocfs2_new_inode(fs, &tmpblkno, S_IFREG | 0755);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, tmpblkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	di->i_flags &= ~OCFS2_VALID_FL;

	ret = ocfs2_write_inode(fs, tmpblkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	fprintf(stdout, "INODE_ALLOC_REPAIR: "
		"Create an inode#%"PRIu64" and invalidate it.\n", tmpblkno);

	if (buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #4
0
errcode_t ocfs2_extend_file(ocfs2_filesys *fs, uint64_t ino, uint64_t new_size)
{
	errcode_t ret = 0;
	char *buf = NULL;
	struct ocfs2_dinode* di = NULL;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;
	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, ino, buf);
	if (ret)
		goto out_free_buf;

	di = (struct ocfs2_dinode *)buf;
	if (di->i_size >= new_size) {
		ret = EINVAL;
		goto out_free_buf;
	}

	di->i_size = new_size;

	ret = ocfs2_write_inode(fs, ino, buf);

out_free_buf:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #5
0
/*
 * dump_dir_entry()
 *
 */
int dump_dir_entry(struct ocfs2_dir_entry *rec, uint64_t blocknr, int offset,
                   int blocksize, char *buf, void *priv_data)
{
    struct list_dir_opts *ls = (struct list_dir_opts *)priv_data;
    char tmp = rec->name[rec->name_len];
    struct ocfs2_dinode *di;
    char perms[20];
    char timestr[40];

    rec->name[rec->name_len] = '\0';

    if (!ls->long_opt) {
        fprintf(ls->out, "\t%-15"PRIu64" %-4u %-4u %-2u %s\n",
                (uint64_t)rec->inode,
                rec->rec_len, rec->name_len, rec->file_type, rec->name);
    } else {
        memset(ls->buf, 0, ls->fs->fs_blocksize);
        ocfs2_read_inode(ls->fs, rec->inode, ls->buf);
        di = (struct ocfs2_dinode *)ls->buf;

        inode_perms_to_str(di->i_mode, perms, sizeof(perms));
        inode_time_to_str(di->i_mtime, timestr, sizeof(timestr));

        fprintf(ls->out, "\t%-15"PRIu64" %10s %3u %5u %5u %15"PRIu64" %s %s\n",
                (uint64_t)rec->inode, perms, di->i_links_count,
                di->i_uid, di->i_gid,
                (uint64_t)di->i_size, timestr, rec->name);
    }

    rec->name[rec->name_len] = tmp;

    return 0;
}
Beispiel #6
0
errcode_t ocfs2_extent_iterate(ocfs2_filesys *fs,
			       uint64_t blkno,
			       int flags,
			       char *block_buf,
			       int (*func)(ocfs2_filesys *fs,
					   struct ocfs2_extent_rec *rec,
					   int tree_depth,
					   uint32_t ccount,
					   uint64_t ref_blkno,
					   int ref_recno,
					   void *priv_data),
			       void *priv_data)
{
	char *buf = NULL;
	struct ocfs2_dinode *inode;
	errcode_t ret;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto out_buf;

	inode = (struct ocfs2_dinode *)buf;

	ret = ocfs2_extent_iterate_inode(fs, inode, flags, block_buf,
					 func, priv_data);

out_buf:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #7
0
static errcode_t create_local_alloc(ocfs2_filesys *fs, uint16_t slot)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;
	uint32_t la_size, found;
	uint64_t la_off, blkno;

	ret = ocfs2_lookup_system_inode(fs, LOCAL_ALLOC_SYSTEM_INODE,
					slot, &blkno);
	if (ret)
		goto bail;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto bail;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		goto bail;

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		goto bail;

	if (di->id1.bitmap1.i_total > 0) {
		fprintf(stderr, "local alloc#%"PRIu64" file not empty."
			"Can't create a new one.\n", blkno);
		goto bail;
	}

	la_size = get_local_alloc_window_bits();

	ret = ocfs2_new_clusters(fs, 1, la_size, &la_off, &found);
	if (ret)
		goto bail;

	if(la_size != found)
		goto bail;

	la = &(di->id2.i_lab);

	la->la_bm_off = ocfs2_blocks_to_clusters(fs, la_off);
	di->id1.bitmap1.i_total = la_size;
	di->id1.bitmap1.i_used = 0;
	memset(la->la_bitmap, 0, la->la_size);
	
	ret = ocfs2_write_inode(fs, blkno, buf);

bail:
	if(buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #8
0
errcode_t ocfs2_chain_iterate(ocfs2_filesys *fs,
			      uint64_t blkno,
			      int (*func)(ocfs2_filesys *fs,
					  uint64_t gd_blkno,
					  int chain_num,
					  void *priv_data),
			       void *priv_data)
{
	int iret = 0;
	char *buf;
	struct ocfs2_dinode *inode;
	errcode_t ret;
	struct chain_context ctxt;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto out_buf;

	inode = (struct ocfs2_dinode *)buf;

	ret = OCFS2_ET_INODE_NOT_VALID;
	if (!(inode->i_flags & OCFS2_VALID_FL))
		goto out_buf;

	ret = OCFS2_ET_INODE_CANNOT_BE_ITERATED;
	if (!(inode->i_flags & OCFS2_CHAIN_FL))
		goto out_buf;

	ret = ocfs2_malloc0(fs->fs_blocksize, &ctxt.gd_buf);
	if (ret)
		goto out_gd_buf;

	ctxt.fs = fs;
	ctxt.func = func;
	ctxt.priv_data = priv_data;

	ret = 0;
	iret |= chain_iterate_cl(&inode->id2.i_chain, &ctxt);
	if (iret & OCFS2_EXTENT_ERROR)
		ret = ctxt.errcode;

	if (iret & OCFS2_EXTENT_CHANGED) {
		/* Do something */
	}

out_gd_buf:
	if (ctxt.gd_buf)
		ocfs2_free(&ctxt.gd_buf);

out_buf:
	ocfs2_free(&buf);

	return ret;
}
static errcode_t truncate_log_check(ocfs2_filesys *fs,
				    uint16_t new_slots)
{
	errcode_t ret = 0;
	uint16_t i;
	uint64_t blkno;
	char *buf = NULL;
	struct ocfs2_dinode *di = NULL;

	uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		verbosef(VL_APP,
			 "%s while allocating inode buffer for "
			 "truncate log check\n",
			 error_message(ret));
		goto bail;
	}

	for (i = new_slots; i < max_slots; ++i) {
		ret = ocfs2_lookup_system_inode(fs, TRUNCATE_LOG_SYSTEM_INODE,
						i, &blkno);
		if (ret) {
			verbosef(VL_APP,
				 "%s while looking up truncate log for "
				 "slot %u during truncate log check\n",
				 error_message(ret), i);
			goto bail;
		}

		ret = ocfs2_read_inode(fs, blkno, buf);
		if (ret) {
			verbosef(VL_APP,
				 "%s while reading inode %"PRIu64" "
				 "during truncate log check\n",
				 error_message(ret), blkno);
			goto bail;
		}

		di = (struct ocfs2_dinode *)buf;

		if (di->id2.i_dealloc.tl_used > 0) {
			ret = TUNEFS_ET_TRUNCATE_LOG_NOT_EMPTY;
			verbosef(VL_APP,
				 "Truncate log for slot %u is not empty\n",
				 i);
			goto bail;
		}
	}

bail:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #10
0
static void create_local_alloc(ocfs2_filesys *fs, uint64_t blkno)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;
	uint32_t la_size, found;
	uint64_t la_off;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		FSWRK_FATAL("not a file");

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		FSWRK_FATAL("not a local alloc file");

	if (di->id1.bitmap1.i_total > 0) {
		FSWRK_WARN("local alloc#%"PRIu64" file not empty."
				"Can't create a new one.\n", blkno);
		goto bail;
	}

	la_size = get_local_alloc_window_bits();

	ret = ocfs2_new_clusters(fs, 1, la_size, &la_off, &found);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
	if(la_size != found)
		FSWRK_FATAL("can't allocate enough clusters for local alloc");

	la = &(di->id2.i_lab);

	la->la_bm_off = la_off;
	di->id1.bitmap1.i_total = la_size;
	di->id1.bitmap1.i_used = 0;
	memset(la->la_bitmap, 0, la->la_size);
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

bail:
	if(buf)
		ocfs2_free(&buf);
	return;
}
static errcode_t local_alloc_check(ocfs2_filesys *fs,
				   uint16_t new_slots)
{
	errcode_t ret = 0;
	uint16_t i;
	uint64_t blkno;
	char *buf = NULL;
	struct ocfs2_dinode *di = NULL;

	uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		verbosef(VL_APP,
			 "%s while allocating inode buffer for local "
			 "alloc check\n",
			 error_message(ret));
		goto bail;
	}

	for (i = new_slots ; i < max_slots; ++i) {
		ret = ocfs2_lookup_system_inode(fs, LOCAL_ALLOC_SYSTEM_INODE,
						i, &blkno);
		if (ret) {
			verbosef(VL_APP,
				 "%s while looking up local alloc for "
				 "slot %u during local alloc check\n",
				 error_message(ret), i);
			break;
		}

		ret = ocfs2_read_inode(fs, blkno, buf);
		if (ret) {
			verbosef(VL_APP,
				 "%s while reading inode %"PRIu64" "
				 "during local alloc check\n",
				 error_message(ret), blkno);
			break;
		}

		di = (struct ocfs2_dinode *)buf;
		if (di->id1.bitmap1.i_total > 0) {
			ret = TUNEFS_ET_LOCAL_ALLOC_NOT_EMPTY;
			verbosef(VL_APP,
				 "Local alloc for slot %u is not empty\n",
				 i);
			break;
		}
	}

bail:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #12
0
int is_dir_inlined(char *dirent_name, unsigned long *i_size,
			   unsigned int *id_count)
{
	int ret;
	uint64_t workplace_blk_no = 1;
	uint64_t testdir_blk_no = 1;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);

	sync();

	ocfs2_malloc_block(fs->fs_io, &buf);

	/*lookup worksplace inode*/
	ret = ocfs2_lookup(fs, sb->s_root_blkno, WORK_PLACE,
			   strlen(WORK_PLACE), NULL, &workplace_blk_no);
	if (ret < 0) {
		fprintf(stderr, "failed to lookup work_place(%s)'s"
			" inode blkno\n", work_place);
		ocfs2_free(&buf);
		exit(ret);
	}

	/*lookup file inode,then read*/
	ret = ocfs2_lookup(fs, workplace_blk_no, dirent_name,
			   strlen(dirent_name), NULL, &testdir_blk_no);
	if (ret < 0) {
		fprintf(stderr, "failed to lookup file(%s/%s)'s"
			" inode blkno\n", work_place, dirent_name);
		ocfs2_free(&buf);
		exit(ret);
	}

	ret = ocfs2_read_inode(fs, testdir_blk_no, buf);
	if (ret < 0) {
		fprintf(stderr, "failed to read file(%s/%s/%s)'s"
			" inode.\n", mount_point, WORK_PLACE, dirent_name);
		ocfs2_free(&buf);
		exit(ret);
	}

	di = (struct ocfs2_dinode *)buf;
	*i_size = di->i_size;
	*id_count = ((di->id2).i_data).id_count;

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
		ret = 1;
	else
		ret = 0;

	ocfs2_free(&buf);
	return ret;
}
Beispiel #13
0
void mess_up_inode_field(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{
	errcode_t ret;
	uint64_t tmpblkno;
	uint32_t clusters = 10;

	char *buf = NULL;
	struct ocfs2_dinode *di;

	create_file(fs, blkno, &tmpblkno);

	if ((type == INODE_SPARSE_SIZE) || (type == INODE_SPARSE_CLUSTERS)) {

		if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super)))
			FSWRK_FATAL("should specfiy a sparse file supported "
				    "volume to do this corruption\n");

		ret = ocfs2_malloc_block(fs->fs_io, &buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		ret = ocfs2_read_inode(fs, tmpblkno, buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		di = (struct ocfs2_dinode *)buf;

		di->i_size = fs->fs_clustersize * 2;

		ret = ocfs2_write_inode(fs, tmpblkno, buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		if (buf)
			ocfs2_free(&buf);
	}

	if ((type == INODE_CLUSTERS) || (type == INODE_SPARSE_CLUSTERS) ||
	    (type == INODE_SPARSE_SIZE)) {
		ret = ocfs2_extend_allocation(fs, tmpblkno, clusters);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
	}

	if (type == REFCOUNT_FLAG_INVALID &&
	    ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)))
		FSWRK_FATAL("should specfiy a norefcount volume\n");
	if (type == REFCOUNT_LOC_INVALID &&
	    !ocfs2_refcount_tree(OCFS2_RAW_SB(fs->fs_super)))
		FSWRK_FATAL("Should specify a refcount supported volume\n");

	damage_inode(fs, tmpblkno, type);
	return;
}
Beispiel #14
0
void mess_up_inline_flag(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{

	int i;
	errcode_t ret;
	char *buf = NULL, file_type[20];
	uint64_t inline_blkno;
	struct ocfs2_dinode *di;
	struct ocfs2_super_block *osb;

	osb = OCFS2_RAW_SB(fs->fs_super);
	if (ocfs2_support_inline_data(osb))
		FSWRK_FATAL("should specfiy a noinline-data supported "
			    "volume to do this corruption\n");

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	for (i = 0; i < 2; i++) {
		if (i == 0) {
			create_file(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Regular file");
		} else {
			create_directory(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Diectory");
		}

		ret = ocfs2_read_inode(fs, inline_blkno, buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		di = (struct ocfs2_dinode *)buf;
		if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
			di->i_dyn_features |= OCFS2_INLINE_DATA_FL;
			ret = ocfs2_write_inode(fs, inline_blkno, buf);
			if (ret)
				FSWRK_COM_FATAL(progname, ret);
		}

		fprintf(stdout, "INLINE_DATA_FLAG_INVALID: "
			"Create an inlined inode#%"PRIu64"(%s) "
			"on a noinline-data supported volume\n",
			inline_blkno, file_type);
	}

	if (buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #15
0
/*
 * NOTE: ocfs2_truncate_inline() also handles fast symlink,
 * since truncating for inline file and fasy symlink are
 * almost the same thing per se.
 */
errcode_t ocfs2_truncate_inline(ocfs2_filesys *fs, uint64_t ino,
				uint64_t new_i_size)
{
	errcode_t ret = 0;
	char *buf = NULL;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_inline_data *idata = NULL;

	if (!(fs->fs_flags & OCFS2_FLAG_RW))
		return OCFS2_ET_RO_FILESYS;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		return ret;

	ret = ocfs2_read_inode(fs, ino, buf);
	if (ret)
		goto out_free_buf;

	di = (struct ocfs2_dinode *)buf;
	if (di->i_size < new_i_size) {
		ret = EINVAL;
		goto out_free_buf;
	}

	idata = &di->id2.i_data;

	if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL) &&
	    !(S_ISLNK(di->i_mode) && !di->i_clusters)) {
		ret = EINVAL;
		goto out_free_buf;
	}

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
		memset(idata->id_data + new_i_size, 0, di->i_size - new_i_size);
	else
		memset(di->id2.i_symlink + new_i_size, 0,
		       di->i_size - new_i_size);

	di->i_size = new_i_size;

	ret = ocfs2_write_inode(fs, ino, buf);

out_free_buf:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #16
0
/* this could certainly be more clever to issue reads in groups */
static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, 
					void *priv_data) 
{
	struct dirblock_data *dd = priv_data;
	struct ocfs2_dir_entry *dirent, *prev = NULL;
	unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; 
	errcode_t ret = 0;

	if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) {
		printf("Directory block %"PRIu64" belongs to directory inode "
		       "%"PRIu64" which isn't allocated.  Ignoring this "
		       "block.", dbe->e_blkno, dbe->e_ino);
		goto out;
	}

	if (dbe->e_ino != dd->last_ino) {
		o2fsck_strings_free(&dd->strings);
		dd->last_ino = dbe->e_ino;

		ret = ocfs2_read_inode(dd->ost->ost_fs, dbe->e_ino,
				       dd->inoblock_buf);
		if (ret) {
			com_err(whoami, ret, "while reading dir inode %"PRIu64,
				dbe->e_ino);
			ret_flags |= OCFS2_DIRENT_ABORT;
			goto out;
		}

		verbosef("dir inode %"PRIu64" i_size %"PRIu64"\n",
			 dbe->e_ino, (uint64_t)di->i_size);

	}

	verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n",
		 dbe->e_blkno, dbe->e_blkcount);

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
		if (dbe->e_ino != dbe->e_blkno)
			goto out;

		memcpy(dd->dirblock_buf, dd->inoblock_buf,
		       dd->fs->fs_blocksize);
		offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
	} else {
		if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
static errcode_t remove_slot_entry(ocfs2_filesys *fs, uint16_t removed_slot)
{
	struct remove_slot_ctxt ctxt = {
		.fs = fs,
		.removed_slot = removed_slot,
		.errcode = 0
	};

	ocfs2_dir_iterate(fs, fs->fs_sysdir_blkno,
			  OCFS2_DIRENT_FLAG_EXCLUDE_DOTS, NULL,
			  remove_slot_iterate, &ctxt);

	return ctxt.errcode;
}

static errcode_t decrease_link_count(ocfs2_filesys *fs, uint16_t blkno)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di  = NULL;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto bail;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (di->i_links_count > 0)
		di->i_links_count--;
	else {
		ret = OCFS2_ET_INODE_NOT_VALID;
		goto bail;
	}

	ret = ocfs2_write_inode(fs, blkno, buf);
bail:
	if (buf)
		ocfs2_free(&buf);
	return ret;
}
Beispiel #18
0
errcode_t handle_slots_system_file(ocfs2_filesys *fs,
                                   int type,
                                   errcode_t (*func)(ocfs2_filesys *fs,
                                           struct ocfs2_dinode *di,
                                           int slot))
{
    errcode_t ret;
    uint64_t blkno;
    int slot, max_slots;
    char *buf = NULL;
    struct ocfs2_dinode *di;

    ret = ocfs2_malloc_block(fs->fs_io, &buf);
    if (ret)
        goto bail;

    di = (struct ocfs2_dinode *)buf;

    max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;

    for (slot = 0; slot < max_slots; slot++) {
        ret = ocfs2_lookup_system_inode(fs,
                                        type,
                                        slot, &blkno);
        if (ret)
            goto bail;

        ret = ocfs2_read_inode(fs, blkno, buf);
        if (ret)
            goto bail;

        if (func) {
            ret = func(fs, di, slot);
            if (ret)
                goto bail;
        }
    }

bail:

    if (buf)
        ocfs2_free(&buf);
    return ret;
}
static errcode_t change_sub_alloc_slot(ocfs2_filesys *fs,
				       uint64_t blkno,
				       struct relink_ctxt *ctxt)
{
	errcode_t ret;
	struct ocfs2_dinode *di = NULL;
	struct ocfs2_extent_block *eb = NULL;

	if (ctxt->inode_type == EXTENT_ALLOC_SYSTEM_INODE) {
		/* change sub alloc bit in the extent block. */
		ret = ocfs2_read_extent_block(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;

		eb = (struct ocfs2_extent_block *)ctxt->ex_buf;
		eb->h_suballoc_slot = ctxt->new_slot;

		ret = ocfs2_write_extent_block(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;
	} else {
		/* change sub alloc bit in the inode. */
		ret = ocfs2_read_inode(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;

		di = (struct ocfs2_dinode *)ctxt->ex_buf;
		di->i_suballoc_slot = ctxt->new_slot;

		ret = ocfs2_write_inode(fs, blkno, ctxt->ex_buf);
		if (ret)
			goto bail;
	}
bail:
	return ret;
}
Beispiel #20
0
static void damage_inode(ocfs2_filesys *fs, uint64_t blkno,
				enum fsck_type type)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		FSWRK_FATAL("not a file");

	switch (type) {
	case INODE_GEN:
		fprintf(stdout, "INODE_GEN: "
			"Corrupt inode#%"PRIu64", change generation "
			" from %u to 0x1234\n", blkno, di->i_fs_generation);
		di->i_fs_generation = 0x1234;
		break;
	case INODE_GEN_FIX:
		fprintf(stdout, "INODE_GEN_FIX: "
			"Corrupt inode#%"PRIu64", change generation "
			" from %u to 0x1234, please answer 'n' when "
			"INODE_GEN error shows in fsck.ocfs2\n",
			blkno, di->i_fs_generation);
		di->i_fs_generation = 0x1234;
		break;
	case INODE_BLKNO:
		fprintf(stdout, "INODE_BLKNO: "
			"Corrupt inode#%"PRIu64", change i_blkno from %"PRIu64
			" to %"PRIu64"\n",
			blkno, di->i_blkno, (di->i_blkno + 100));
		di->i_blkno += 100;
		break;
	case INODE_NZ_DTIME:
		fprintf(stdout, "INODE_NZ_DTIME: "
			"Corrupt inode#%"PRIu64", change i_dtime from %"PRIu64
			" to 100\n", blkno, di->i_dtime);
		di->i_dtime = 100;
		break;
	case INODE_SUBALLOC:
		fprintf(stdout, "INODE_SUBALLOC: "
			"Corrupt inode#%"PRIu64", change i_suballoc_slot"
			" from %u to %u\n", blkno, di->i_suballoc_slot,
			(di->i_suballoc_slot + 10));
		di->i_suballoc_slot += 10;
		break;
	case INODE_SIZE:
		fprintf(stdout, "INODE_SIZE: "
			"Corrupt inode#%"PRIu64", change i_size"
			" from %"PRIu64" to %"PRIu64"\n",
			 blkno, di->i_size, (di->i_size + 100));
		di->i_size += 100;
		break;
	case INODE_SPARSE_SIZE:
		fprintf(stdout, "INODE_SPARSE_SIZE: "
			"Corrupt inode#%"PRIu64", change i_size "
			"from %"PRIu64" to %u\n",
			 blkno, di->i_size, fs->fs_clustersize);
		di->i_size = fs->fs_clustersize;
		break;
	case INODE_CLUSTERS:
		fprintf(stdout, "INODE_CLUSTERS: "
			"Corrupt inode#%"PRIu64", change i_clusters"
			" from %u to 0\n", blkno, di->i_clusters);
		di->i_clusters = 0;
		break;
	case INODE_SPARSE_CLUSTERS:
		fprintf(stdout, "INODE_SPARSE_CLUSTERS: "
			"Corrupt inode#%"PRIu64", change i_clusters"
			" from %u to 0\n", blkno, di->i_clusters);
		di->i_clusters = 0;
		break;
	case INODE_COUNT:
		di->i_links_count = 0;
		fprintf(stdout, "INODE_COUNT: "
			"Corrupte inode#%"PRIu64", set link count to 0\n",
			blkno);
		break;
	case INODE_BLOCK_ECC:
		fprintf(stdout, "INODE_BLOCK_ECC: "
			"Corrupte inode#%"PRIu64", set both i_check.bc_crc32e"
			"=%"PRIu64" and i_check.bc_ecc=%"PRIu64" to 0x1234\n",
			blkno, di->i_check.bc_crc32e, di->i_check.bc_ecc);
		di->i_check.bc_crc32e = 0x1234;
		di->i_check.bc_ecc = 0x1234;
		break;
	case INODE_VALID_FLAG:
		fprintf(stdout, "INODE_VALID_FLAG: "
			"Corrupt inode#%"PRIu64", clear inode valid flag\n",
			blkno);
		di->i_flags &= ~OCFS2_VALID_FL;
		break;
	case REFCOUNT_FLAG_INVALID:
		di->i_dyn_features |= OCFS2_HAS_REFCOUNT_FL;
		fprintf(stdout, "REFCOUNT_FLAG_INVALD: "
			"Corrupt inode#%"PRIu64", add refcount feature\n",
			blkno);
		break;
	case REFCOUNT_LOC_INVALID:
		di->i_refcount_loc = 100;
		fprintf(stdout, "REFCOUNT_LOC_INVALID: "
			"Create an inode#%"PRIu64","
			"whose i_refcount_loc has been messed up.\n",
			blkno);
		break;
	default:
		FSWRK_FATAL("Invalid type[%d]\n", type);
	}

	if (type != INODE_BLOCK_ECC)
		ret = ocfs2_write_inode(fs, blkno, buf);
	else
		ret = ocfs2_write_inode_without_meta_ecc(fs, blkno, buf);

	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	if (buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #21
0
void mess_up_dup_clusters(ocfs2_filesys *fs, enum fsck_type type,
			  uint64_t blkno)
{
	errcode_t err;
	char *buf = NULL;
	uint64_t inode1_blkno, inode2_blkno;
	struct ocfs2_dinode *di1, *di2;
	struct ocfs2_extent_list *el1, *el2;

	err = ocfs2_malloc_blocks(fs->fs_io, 2, &buf);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	create_file(fs, blkno, &inode1_blkno);

	di1 = (struct ocfs2_dinode *)buf;
	err = ocfs2_read_inode(fs, inode1_blkno, (char *)di1);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
		if (di1->i_dyn_features & OCFS2_INLINE_DATA_FL) {
			di1->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
			err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1);
			if (err)
				FSWRK_COM_FATAL(progname, err);
		}
	}

	if (type != DUP_CLUSTERS_SYSFILE_CLONE) {

		create_file(fs, blkno, &inode2_blkno);
		di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize);
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (ocfs2_support_inline_data(OCFS2_RAW_SB(fs->fs_super))) {
			if (di2->i_dyn_features & OCFS2_INLINE_DATA_FL) {
				di2->i_dyn_features &= ~OCFS2_INLINE_DATA_FL;
				err = ocfs2_write_inode(fs, inode2_blkno,
							(char *)di2);
				if (err)
					FSWRK_COM_FATAL(progname, err);
			}
		}

		err = ocfs2_extend_allocation(fs, inode2_blkno, 1);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		/* Re-read the inode with the allocation */
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		/* Set i_size to non-zero so that the allocation is valid */
		di2->i_size = fs->fs_clustersize;
		err = ocfs2_write_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (type == DUP_CLUSTERS_CLONE)
			fprintf(stdout, "DUP_CLUSTERS_CLONE: "
				"Create two inodes #%"PRIu64" and #%"PRIu64
				" by allocating same cluster to them.\n",
				inode1_blkno, inode2_blkno);
		else
			fprintf(stdout, "DUP_CLUSTERS_DELETE: "
				"Create two inodes #%"PRIu64" and #%"PRIu64
				" by allocating same cluster to them.\n",
				inode1_blkno, inode2_blkno);
	} else {
		/* Here use journal file*/
		err = ocfs2_lookup_system_inode(fs, JOURNAL_SYSTEM_INODE, 0,
						&inode2_blkno);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		di2 = (struct ocfs2_dinode *)(buf + fs->fs_blocksize);
		err = ocfs2_read_inode(fs, inode2_blkno, (char *)di2);
		if (err)
			FSWRK_COM_FATAL(progname, err);

		if (di2->id2.i_list.l_tree_depth)
			FSWRK_FATAL("Journal inode has non-zero tree "
				    "depth.  fswreck can't use it for "
				    "DUP_CLUSTERS_SYSFILE_CLONE\n");

		fprintf(stdout, "DUP_CLUSTERS_SYSFILE_CLONE: "
			"Allocate same cluster to journal file "
			"#%"PRIu64" and regular file #%"PRIu64".\n",
			inode1_blkno, inode2_blkno);
	}

	el1 = &(di1->id2.i_list);
	el2 = &(di2->id2.i_list);


	el1->l_next_free_rec = 1;
	el1->l_recs[0] = el2->l_recs[0];

	di1->i_size =
		ocfs2_clusters_to_bytes(fs, el1->l_recs[0].e_leaf_clusters);
	di1->i_clusters = di2->i_clusters;

	err = ocfs2_write_inode(fs, inode1_blkno, (char *)di1);
	if (err)
		FSWRK_COM_FATAL(progname, err);

	ocfs2_free(&buf);
}
Beispiel #22
0
void mess_up_inline_inode(ocfs2_filesys *fs, enum fsck_type type, uint64_t blkno)
{
	int i;
	errcode_t ret;
	char *buf = NULL, file_type[20];
	uint64_t inline_blkno;
	struct ocfs2_dinode *di;
	uint16_t max_inline_sz;
	struct ocfs2_super_block *osb;

	osb = OCFS2_RAW_SB(fs->fs_super);
	if (!ocfs2_support_inline_data(osb))
		FSWRK_FATAL("Should specify a inline-data supported "
			    "volume to do this corruption\n");

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	for (i = 0; i < 2; i++) {
		if (i == 0) {
			create_file(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Regular file");
		} else {
			create_directory(fs, blkno, &inline_blkno);
			snprintf(file_type, 20, "%s", "Diectroy");
		}

		ret = ocfs2_read_inode(fs, inline_blkno, buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);

		di = (struct ocfs2_dinode *)buf;
		max_inline_sz =
			ocfs2_max_inline_data_with_xattr(fs->fs_blocksize, di);

		if (!(di->i_dyn_features & OCFS2_INLINE_DATA_FL))
			di->i_dyn_features |= OCFS2_INLINE_DATA_FL;

		switch (type) {
		case INLINE_DATA_COUNT_INVALID:
			di->id2.i_data.id_count = 0;
			fprintf(stdout, "INLINE_DATA_COUNT_INVALID: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose id_count has been messed up.\n",
				inline_blkno, file_type);
			break;
		case INODE_INLINE_SIZE:
			di->i_size = max_inline_sz + 1;
			fprintf(stdout, "INODE_INLINE_SIZE: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose i_size has been messed up.\n",
				inline_blkno, file_type);
			break;
		case INODE_INLINE_CLUSTERS:
			di->i_clusters = 1;
			fprintf(stdout, "INODE_INLINE_CLUSTERS: "
				"Create an inlined inode#%"PRIu64"(%s),"
				"whose i_clusters has been messed up.\n",
				inline_blkno, file_type);
			break;

		default:
			FSWRK_FATAL("Invalid type[%d]\n", type);
		}

		ret = ocfs2_write_inode(fs, inline_blkno, buf);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
	}

	if (buf)
		ocfs2_free(&buf);

	return;
}
Beispiel #23
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno;
	int c;
	char *filename, *buf;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_it wi;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "bei:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}
	
	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
		fprintf(stderr, "You must specify an inode block\n");
		print_usage();
		return 1;
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}
	filename = argv[optind];
	
	ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	memset(&wi, 0, sizeof(wi));

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	fprintf(stdout, "OCFS2 inode %"PRIu64" on \"%s\"\n",
		blkno, filename);

	ret = ocfs2_malloc_block(fs->fs_io, &wi.gd_buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating gd buffer");
		goto out_free;
	}

	wi.di = di;
	wi.last_chain = -1;
	ret = ocfs2_chain_iterate(fs, blkno,
				  walk_chain_func,
				  &wi);
	if (ret) {
		com_err(argv[0], ret,
			"while walking extents");
	}

out_free:
	if (wi.gd_buf)
		ocfs2_free(&wi.gd_buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
Beispiel #24
0
errcode_t ocfs2_fill_heartbeat_desc(ocfs2_filesys *fs,
				    struct o2cb_region_desc *desc)
{
	errcode_t ret;
	char *filename;
	char *buf = NULL;
	uint64_t blkno, blocks, start_block;
	uint32_t block_bits, cluster_bits;
	int sectsize, sectsize_bits;
	struct ocfs2_dinode *di;
	struct ocfs2_extent_rec *rec;

	ret = ocfs2_get_device_sectsize(fs->fs_devname, &sectsize);
	if (ret) {
		if (ret == OCFS2_ET_CANNOT_DETERMINE_SECTOR_SIZE)
			sectsize = OCFS2_MIN_BLOCKSIZE;
		else
			goto leave;
	}

	sectsize_bits = ffs(sectsize) - 1;

	filename = ocfs2_system_inodes[HEARTBEAT_SYSTEM_INODE].si_name;

	ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, filename,
			   strlen(filename),  NULL, &blkno);
	if (ret)
		goto leave;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto leave;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto leave;

	di = (struct ocfs2_dinode *)buf;
	if (di->id2.i_list.l_tree_depth || 
	    di->id2.i_list.l_next_free_rec != 1) {
		ret = OCFS2_ET_BAD_HEARTBEAT_FILE;
		goto leave;
	}
	rec = &(di->id2.i_list.l_recs[0]);

	block_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
	cluster_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;

	if (block_bits < sectsize_bits) {
		ret = OCFS2_ET_BLOCK_SIZE_TOO_SMALL_FOR_HARDWARE;
		goto leave;
	}

	blocks = ocfs2_rec_clusters(0, rec) << cluster_bits;
	blocks >>= block_bits;

	if (blocks > O2NM_MAX_NODES)
		blocks = O2NM_MAX_NODES;

	start_block = rec->e_blkno << block_bits;
	start_block >>= sectsize_bits;

	desc->r_name			= fs->uuid_str;
	desc->r_device_name		= fs->fs_devname;
	desc->r_block_bytes		= sectsize;
	desc->r_start_block		= start_block;
	desc->r_blocks			= blocks;

leave:
	if (buf)
		ocfs2_free(&buf);

	return ret;
}
Beispiel #25
0
int main(int argc, char *argv[])
{
	errcode_t ret;
	uint64_t blkno, sys_blkno;
	int c;
	char *filename, *buf;
	const char *bitmap_name = ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name;
	ocfs2_filesys *fs;
	struct ocfs2_dinode *di;
	struct walk_block wb;

	blkno = OCFS2_SUPER_BLOCK_BLKNO;

	initialize_ocfs_error_table();

	while ((c = getopt(argc, argv, "i:")) != EOF) {
		switch (c) {
			case 'i':
				blkno = read_number(optarg);
				if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) {
					fprintf(stderr,
						"Invalid inode block: %s\n",
						optarg);
					print_usage();
					return 1;
				}
				break;

			default:
				print_usage();
				return 1;
				break;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing filename\n");
		print_usage();
		return 1;
	}
	filename = argv[optind];

	ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs);
	if (ret) {
		com_err(argv[0], ret,
			"while opening file \"%s\"", filename);
		goto out;
	}

	if (blkno == OCFS2_SUPER_BLOCK_BLKNO) {
		sys_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno;

		ret = ocfs2_lookup(fs, sys_blkno, bitmap_name, 
				   strlen(bitmap_name), NULL, &blkno);
		if (ret) {
			com_err(argv[0], ret,
				"while looking up \"%s\"", bitmap_name);
			goto out;
		}
	}

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating inode buffer");
		goto out_close;
	}

	memset(&wb, 0, sizeof(wb));

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

	di = (struct ocfs2_dinode *)buf;

	wb.di = di;
	ret = ocfs2_malloc_block(fs->fs_io, &wb.buf);
	if (ret) {
		com_err(argv[0], ret,
			"while allocating block buffer");
		goto out_free;
	}

	ret = ocfs2_block_iterate(fs, blkno, 0,
				  walk_blocks_func,
				  &wb);
	if (ret) {
		com_err(argv[0], ret,
			"while walking blocks");
		goto out_free;
	}

	di->id1.bitmap1.i_used = wb.used;

	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret) {
		com_err(argv[0], ret, "while reading inode %"PRIu64, blkno);
		goto out_free;
	}

out_free:
	if (wb.buf)
		ocfs2_free(&wb.buf);

	ocfs2_free(&buf);

out_close:
	ret = ocfs2_close(fs);
	if (ret) {
		com_err(argv[0], ret,
			"while closing file \"%s\"", filename);
	}

out:
	return 0;
}
Beispiel #26
0
static void damage_local_alloc(ocfs2_filesys *fs,
				uint64_t blkno, enum fsck_type type)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_local_alloc *la;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		FSWRK_FATAL("not a file");

	if (!(di->i_flags & OCFS2_LOCAL_ALLOC_FL))
		FSWRK_FATAL("not a local alloc file");
	
	la = &(di->id2.i_lab);

	/* For LALLOC_BM_OVERRUN, LALLOC_BM_STRADDLE,LALLOC_BM_SIZE,
	 * LALLOC_USED_OVERRUN, LALLOC_CLEAR, i_total must be greater than 0.
	 * So check it first.
	 */
	if (type == LALLOC_BM_OVERRUN || type == LALLOC_BM_STRADDLE ||
		type == LALLOC_BM_SIZE || type == LALLOC_USED_OVERRUN)
		if (di->id1.bitmap1.i_total == 0) {
			FSWRK_WARN("local inode#%"PRIu64" is empty, so can't"
					"corrupt it for type[%d]\n",
					blkno, type);
			goto bail;
		}
	
	switch (type) {
	case LALLOC_SIZE:
	case LALLOC_CLEAR:
		if (type == LALLOC_SIZE)
			fprintf(stdout, "LALLOC_SIZE: ");
		else
			fprintf(stdout, "LALLOC_CLEAR: ");
		fprintf(stdout,	"Corrupt local alloc inode#%"PRIu64
			", change size from %u to %u\n", blkno, la->la_size,
			(ocfs2_local_alloc_size(fs->fs_blocksize) + 10));
		la->la_size = ocfs2_local_alloc_size(fs->fs_blocksize) + 10;
		break;
	case LALLOC_NZ_USED:
		di->id1.bitmap1.i_total = 0;
		di->id1.bitmap1.i_used = 10;
		fprintf(stdout, "LALLOC_NZ_USED: "
			"Corrupt local alloc inode#%"PRIu64", total = %d "
			" used =  %d\n",blkno,  di->id1.bitmap1.i_total,
			di->id1.bitmap1.i_used);
		break;
	case LALLOC_NZ_BM:
		di->id1.bitmap1.i_total = 0;
		la->la_bm_off = 100;
		fprintf(stdout, "LALLOC_NZ_BM: "
			"Corrupt local alloc inode#%"PRIu64", total = %d "
			" la_bm_off =  %d\n",blkno,  di->id1.bitmap1.i_total,
			la->la_bm_off);
		break;
	case LALLOC_BM_OVERRUN:
	case LALLOC_BM_STRADDLE:
		la->la_bm_off = fs->fs_clusters + 10;
		if (type == LALLOC_BM_OVERRUN)
			fprintf(stdout, "LALLOC_BM_OVERRUN: ");
		else
			fprintf(stdout, "LALLOC_BM_STRADDLE: ");
		fprintf(stdout, "Corrupt local alloc inode#%"PRIu64
			", la_bm_off =%u\n", blkno,  la->la_bm_off);
		break;
	case LALLOC_BM_SIZE:
		fprintf(stdout, "LALLOC_SIZE: "
			"Corrupt local alloc inode#%"PRIu64", change i_total"
			" from %u to %u\n", blkno, di->id1.bitmap1.i_total,
			(la->la_size * 8 + 10));
		di->id1.bitmap1.i_total = la->la_size * 8 + 10;
		break;
	case LALLOC_USED_OVERRUN:
		fprintf(stdout, "LALLOC_USED_OVERRUN: "
			"Corrupt local alloc inode#%"PRIu64", change i_used"
			" from %u to %u\n", blkno, di->id1.bitmap1.i_used,
			(di->id1.bitmap1.i_total + 10));
		di->id1.bitmap1.i_used = di->id1.bitmap1.i_total + 10;
		break;
	default:
		FSWRK_FATAL("Unknown type = %d", type);
	}
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
bail:
	if (buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #27
0
/* this could certainly be more clever to issue reads in groups */
static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, 
					void *priv_data) 
{
	struct dirblock_data *dd = priv_data;
	struct ocfs2_dir_entry *dirent, *prev = NULL;
	unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize;
	unsigned int write_off, saved_reclen;
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; 
	errcode_t ret = 0;

	if (!o2fsck_test_inode_allocated(dd->ost, dbe->e_ino)) {
		printf("Directory block %"PRIu64" belongs to directory inode "
		       "%"PRIu64" which isn't allocated.  Ignoring this "
		       "block.", dbe->e_blkno, dbe->e_ino);
		goto out;
	}

	if (dbe->e_ino != dd->last_ino) {
		o2fsck_strings_free(&dd->strings);
		dd->last_ino = dbe->e_ino;

		ret = ocfs2_read_inode(dd->ost->ost_fs, dbe->e_ino,
				       dd->inoblock_buf);
		if (ret == OCFS2_ET_BAD_CRC32) {
			if (prompt(dd->ost, PY, PR_BAD_CRC32, 
						"Directory inode %"PRIu64" "
						"has bad CRC32. Recalculate CRC32 "
						"and write inode block?", dbe->e_ino)) {
				ocfs2_write_inode(dd->ost->ost_fs, dbe->e_ino,
						dd->inoblock_buf);
			}
		} else if (ret) {
			com_err(whoami, ret, "while reading dir inode %"PRIu64,
				dbe->e_ino);
			ret_flags |= OCFS2_DIRENT_ABORT;
			goto out;
		}

		verbosef("dir inode %"PRIu64" i_size %"PRIu64"\n",
			 dbe->e_ino, (uint64_t)di->i_size);

		/* Set the flag for index rebuilding */
		if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super))
			&& !(di->i_dyn_features & OCFS2_INLINE_DATA_FL)
			&& !(di->i_dyn_features & OCFS2_INDEXED_DIR_FL) 
			&& prompt(dd->ost, PY, PR_DX_TREE_MISSING, 
				  "Directory %"PRIu64" is missing index. "
				  "Rebuild?", dbe->e_ino))
				ret_flags |= OCFS2_DIRENT_CHANGED;

	}

	verbosef("dir block %"PRIu64" block offs %"PRIu64" in ino\n",
		 dbe->e_blkno, dbe->e_blkcount);

	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
		if (dbe->e_ino != dbe->e_blkno)
			goto out;

		memcpy(dd->dirblock_buf, dd->inoblock_buf,
		       dd->fs->fs_blocksize);
		offset = offsetof(struct ocfs2_dinode, id2.i_data.id_data);
	} else {
		if (dbe->e_blkcount >= ocfs2_blocks_in_bytes(dd->fs,
Beispiel #28
0
static void create_truncate_log(ocfs2_filesys *fs, uint64_t blkno,
				uint16_t used, uint32_t clusters)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	uint16_t i, max;
	uint32_t found;
	uint64_t begin;

	max = ocfs2_truncate_recs_per_inode(fs->fs_blocksize);
	if (used > max)
		FSWRK_FATAL("recnum exceeds the limit of truncate log");

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		FSWRK_FATAL("not a valid file");

	if (!(di->i_flags & OCFS2_DEALLOC_FL))
		FSWRK_FATAL("not a valid truncate log");
	
	tl = &di->id2.i_dealloc;

	if (tl->tl_used > 0) {
		FSWRK_WARN("truncate log#%"PRIu64" file not empty."
				"Can't create a new one.\n", blkno);
		goto bail;
	}

	used = min(used, tl->tl_count);
	tl->tl_used = used;

	for (i = 0; i < tl->tl_used; i++) {
		ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found);
		if (ret)
			FSWRK_COM_FATAL(progname, ret);
		
		tl->tl_recs[i].t_start = 
			cpu_to_le32(ocfs2_blocks_to_clusters(fs, begin));
		tl->tl_recs[i].t_clusters = cpu_to_le32(found);
	}

	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

bail:
	if(buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #29
0
static void damage_truncate_log(ocfs2_filesys *fs,
				uint64_t blkno, enum fsck_type type, int recnum)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	struct ocfs2_truncate_rec *tr;

	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL))
		FSWRK_FATAL("not a valid file");

	if (!(di->i_flags & OCFS2_DEALLOC_FL))
		FSWRK_FATAL("not a valid truncate log");
	
	tl = &di->id2.i_dealloc;

	/* For TRUNCATE_REC_START_RANGE, TRUNCATE_REC_WRAP, TRUNCATE_REC_RANGE,
	 * tl_used must be greater than 0 and recnum must be less than tl_used.
	 * So check it first.
	 */
	if (type == TRUNCATE_REC_START_RANGE || type == TRUNCATE_REC_WRAP ||
		type == TRUNCATE_REC_RANGE) {
		if (tl->tl_used == 0) {
			FSWRK_WARN("truncate log#%"PRIu64" is empty, so can't"
					"corrupt it for type[%d]\n",
					blkno, type);
			goto bail;
		}
		
		if(tl->tl_used <= recnum) {
			FSWRK_WARN("truncate log#%"PRIu64" can't corrupt "
					"item[%d] corrupt it for type[%d]\n",
					blkno, recnum, type);
			goto bail;
		}
	}
	
	switch (type) {
	case DEALLOC_COUNT:
		fprintf(stdout, "DEALLOC_COUNT: "
			"Corrupt truncate log inode#%"PRIu64", change tl_count"
			" from %u to %u\n",
			blkno, tl->tl_count, (tl->tl_count + 10));
		tl->tl_count += 10;
		break;
	case DEALLOC_USED:
		fprintf(stdout, "DEALLOC_USED: "
			"Corrupt truncate log inode#%"PRIu64", change tl_used"
			" from %u to %u\n",
			blkno, tl->tl_used, (tl->tl_count + 10));
		tl->tl_used = tl->tl_count + 10;
		break;
	case TRUNCATE_REC_START_RANGE:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_START_RANGE: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_start from %u to %u\n",
			blkno, recnum, tr->t_start, (fs->fs_clusters + 10));
		tr->t_start = fs->fs_clusters + 10;
		break;
	case TRUNCATE_REC_WRAP:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_WRAP: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_start from %u to 10000\n,"
			"change t_clusters from %u to %u\n",
			blkno, recnum,
			tr->t_start,tr->t_clusters, (UINT32_MAX - 10));
		tr->t_start = 10000;
		tr->t_clusters = UINT32_MAX - 10;
		break;
	case TRUNCATE_REC_RANGE:
		tr = &tl->tl_recs[recnum];
		fprintf(stdout, "TRUNCATE_REC_RANGE: "
			"Corrupt truncate log inode#%"PRIu64",rec#%d "
			"change t_clusters from %u to %u\n",
			blkno, recnum, tr->t_clusters, (fs->fs_clusters + 10));
		tr->t_clusters = fs->fs_clusters + 10;
		break;
	default:
		FSWRK_FATAL("Unknown type = %d", type);
	}
	
	ret = ocfs2_write_inode(fs, blkno, buf);
	if (ret)
		FSWRK_COM_FATAL(progname, ret);
bail:
	if (buf)
		ocfs2_free(&buf);
	return;
}
Beispiel #30
0
static errcode_t create_truncate_log(ocfs2_filesys *fs, uint16_t slot)
{
	errcode_t ret;
	char *buf = NULL;
	struct ocfs2_dinode *di;
	struct ocfs2_truncate_log *tl;
	uint16_t i, used = 10;
	uint32_t found, clusters = 10;
	uint64_t begin, blkno;

	ret = ocfs2_lookup_system_inode(fs, TRUNCATE_LOG_SYSTEM_INODE,
					slot, &blkno);
	if (ret)
		goto bail;
	
	ret = ocfs2_malloc_block(fs->fs_io, &buf);
	if (ret)
		goto bail;

	ret = ocfs2_read_inode(fs, blkno, buf);
	if (ret)
		goto bail;

	di = (struct ocfs2_dinode *)buf;

	if (!(di->i_flags & OCFS2_VALID_FL)) {
		fprintf(stderr,"not a valid file\n");
		goto bail;
	}

	if (!(di->i_flags & OCFS2_DEALLOC_FL)) {
		fprintf(stderr,"not a valid truncate log\n");
		goto bail;
	}
	
	tl = &di->id2.i_dealloc;

	if (le16_to_cpu(tl->tl_used) > 0) {
		fprintf(stderr,"truncate log#%"PRIu64" file not empty."
			"Can't create a new one.\n", blkno);
		goto bail;
	}

	tl->tl_used = used;

	for (i = 0; i < tl->tl_used; i++) {
		ret = ocfs2_new_clusters(fs, 1, clusters, &begin, &found);
		if (ret)
			goto bail;
		
		tl->tl_recs[i].t_start = 
			ocfs2_blocks_to_clusters(fs, begin);
		tl->tl_recs[i].t_clusters = found;
	}

	ret = ocfs2_write_inode(fs, blkno, buf);

bail:
	if(buf)
		ocfs2_free(&buf);
	return ret;
}