Example #1
0
/* post the our slot info stuff into it's destination bh and write it
 * out. */
int ocfs2_update_disk_slots(struct ocfs2_super *osb,
			    struct ocfs2_slot_info *si)
{
	int status, i;
	__le16 *disk_info = (__le16 *) si->si_bh->b_data;

	spin_lock(&si->si_lock);
	for (i = 0; i < si->si_size; i++)
		disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
	spin_unlock(&si->si_lock);

	status = ocfs2_write_block(osb, si->si_bh, si->si_inode);
	if (status < 0)
		mlog_errno(status);

	return status;
}
Example #2
0
static int ocfs2_update_disk_slot(struct ocfs2_super *osb,
				  struct ocfs2_slot_info *si,
				  int slot_num)
{
	int status;
	struct buffer_head *bh;

	spin_lock(&osb->osb_lock);
	if (si->si_extended)
		ocfs2_update_disk_slot_extended(si, slot_num, &bh);
	else
		ocfs2_update_disk_slot_old(si, slot_num, &bh);
	spin_unlock(&osb->osb_lock);

	status = ocfs2_write_block(osb, bh, INODE_CACHE(si->si_inode));
	if (status < 0)
		mlog_errno(status);

	return status;
}
Example #3
0
static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
				      int dirty)
{
	int status;
	unsigned int flags;
	struct ocfs2_journal *journal = osb->journal;
	struct buffer_head *bh = journal->j_bh;
	struct ocfs2_dinode *fe;

	mlog_entry_void();

	fe = (struct ocfs2_dinode *)bh->b_data;
	if (!OCFS2_IS_VALID_DINODE(fe)) {
		/* This is called from startup/shutdown which will
		 * handle the errors in a specific manner, so no need
		 * to call ocfs2_error() here. */
		mlog(ML_ERROR, "Journal dinode %llu  has invalid "
		     "signature: %.*s",
		     (unsigned long long)le64_to_cpu(fe->i_blkno), 7,
		     fe->i_signature);
		status = -EIO;
		goto out;
	}

	flags = le32_to_cpu(fe->id1.journal1.ij_flags);
	if (dirty)
		flags |= OCFS2_JOURNAL_DIRTY_FL;
	else
		flags &= ~OCFS2_JOURNAL_DIRTY_FL;
	fe->id1.journal1.ij_flags = cpu_to_le32(flags);

	status = ocfs2_write_block(osb, bh, journal->j_inode);
	if (status < 0)
		mlog_errno(status);

out:
	mlog_exit(status);
	return status;
}
Example #4
0
/*
 * We want to free the bitmap bits outside of any recovery context as
 * we'll need a cluster lock to do so, but we must clear the local
 * alloc before giving up the recovered nodes journal. To solve this,
 * we kmalloc a copy of the local alloc before it's change for the
 * caller to process with ocfs2_complete_local_alloc_recovery
 */
int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
				     int slot_num,
				     struct ocfs2_dinode **alloc_copy)
{
	int status = 0;
	struct buffer_head *alloc_bh = NULL;
	struct inode *inode = NULL;
	struct ocfs2_dinode *alloc;

	trace_ocfs2_begin_local_alloc_recovery(slot_num);

	*alloc_copy = NULL;

	inode = ocfs2_get_system_file_inode(osb,
					    LOCAL_ALLOC_SYSTEM_INODE,
					    slot_num);
	if (!inode) {
		status = -EINVAL;
		mlog_errno(status);
		goto bail;
	}

	inode_lock(inode);

	status = ocfs2_read_inode_block_full(inode, &alloc_bh,
					     OCFS2_BH_IGNORE_CACHE);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	*alloc_copy = kmalloc(alloc_bh->b_size, GFP_KERNEL);
	if (!(*alloc_copy)) {
		status = -ENOMEM;
		goto bail;
	}
	memcpy((*alloc_copy), alloc_bh->b_data, alloc_bh->b_size);

	alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
	ocfs2_clear_local_alloc(alloc);

	ocfs2_compute_meta_ecc(osb->sb, alloc_bh->b_data, &alloc->i_check);
	status = ocfs2_write_block(osb, alloc_bh, INODE_CACHE(inode));
	if (status < 0)
		mlog_errno(status);

bail:
	if (status < 0) {
		kfree(*alloc_copy);
		*alloc_copy = NULL;
	}

	brelse(alloc_bh);

	if (inode) {
		inode_unlock(inode);
		iput(inode);
	}

	if (status)
		mlog_errno(status);
	return status;
}
Example #5
0
static int ocfs2_read_locked_inode(struct inode *inode,
				   struct ocfs2_find_inode_args *args)
{
	struct super_block *sb;
	struct ocfs2_super *osb;
	struct ocfs2_dinode *fe;
	struct buffer_head *bh = NULL;
	int status, can_lock, lock_level = 0;
	u32 generation = 0;

	status = -EINVAL;
	sb = inode->i_sb;
	osb = OCFS2_SB(sb);

	/*
	 * To improve performance of cold-cache inode stats, we take
	 * the cluster lock here if possible.
	 *
	 * Generally, OCFS2 never trusts the contents of an inode
	 * unless it's holding a cluster lock, so taking it here isn't
	 * a correctness issue as much as it is a performance
	 * improvement.
	 *
	 * There are three times when taking the lock is not a good idea:
	 *
	 * 1) During startup, before we have initialized the DLM.
	 *
	 * 2) If we are reading certain system files which never get
	 *    cluster locks (local alloc, truncate log).
	 *
	 * 3) If the process doing the iget() is responsible for
	 *    orphan dir recovery. We're holding the orphan dir lock and
	 *    can get into a deadlock with another process on another
	 *    node in ->delete_inode().
	 *
	 * #1 and #2 can be simply solved by never taking the lock
	 * here for system files (which are the only type we read
	 * during mount). It's a heavier approach, but our main
	 * concern is user-accessible files anyway.
	 *
	 * #3 works itself out because we'll eventually take the
	 * cluster lock before trusting anything anyway.
	 */
	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		&& !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)
		&& !ocfs2_mount_local(osb);

	trace_ocfs2_read_locked_inode(
		(unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock);

	/*
	 * To maintain backwards compatibility with older versions of
	 * ocfs2-tools, we still store the generation value for system
	 * files. The only ones that actually matter to userspace are
	 * the journals, but it's easier and inexpensive to just flag
	 * all system files similarly.
	 */
	if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		generation = osb->fs_generation;

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,
				  OCFS2_LOCK_TYPE_META,
				  generation, inode);

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,
				  OCFS2_LOCK_TYPE_OPEN,
				  0, inode);

	if (can_lock) {
		status = ocfs2_open_lock(inode);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
		status = ocfs2_inode_lock(inode, NULL, lock_level);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
	}

	if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {
		status = ocfs2_try_open_lock(inode, 0);
		if (status) {
			make_bad_inode(inode);
			return status;
		}
	}

	if (can_lock) {
		if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
			status = ocfs2_filecheck_read_inode_block_full(inode,
						&bh, OCFS2_BH_IGNORE_CACHE, 0);
		else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
			status = ocfs2_filecheck_read_inode_block_full(inode,
						&bh, OCFS2_BH_IGNORE_CACHE, 1);
		else
			status = ocfs2_read_inode_block_full(inode,
						&bh, OCFS2_BH_IGNORE_CACHE);
	} else {
		status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
		/*
		 * If buffer is in jbd, then its checksum may not have been
		 * computed as yet.
		 */
		if (!status && !buffer_jbd(bh)) {
			if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_CHK)
				status = ocfs2_filecheck_validate_inode_block(
								osb->sb, bh);
			else if (args->fi_flags & OCFS2_FI_FLAG_FILECHECK_FIX)
				status = ocfs2_filecheck_repair_inode_block(
								osb->sb, bh);
			else
				status = ocfs2_validate_inode_block(
								osb->sb, bh);
		}
	}
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	status = -EINVAL;
	fe = (struct ocfs2_dinode *) bh->b_data;

	/*
	 * This is a code bug. Right now the caller needs to
	 * understand whether it is asking for a system file inode or
	 * not so the proper lock names can be built.
	 */
	mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) !=
			!!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE),
			"Inode %llu: system file state is ambigous\n",
			(unsigned long long)args->fi_blkno);

	if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
	    S_ISBLK(le16_to_cpu(fe->i_mode)))
		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));

	ocfs2_populate_inode(inode, fe, 0);

	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));

	if (buffer_dirty(bh) && !buffer_jbd(bh)) {
		if (can_lock) {
			ocfs2_inode_unlock(inode, lock_level);
			lock_level = 1;
			ocfs2_inode_lock(inode, NULL, lock_level);
		}
		status = ocfs2_write_block(osb, bh, INODE_CACHE(inode));
		if (status < 0) {
			mlog_errno(status);
			goto bail;
		}
	}

	status = 0;

bail:
	if (can_lock)
		ocfs2_inode_unlock(inode, lock_level);

	if (status < 0)
		make_bad_inode(inode);

	brelse(bh);

	return status;
}
/*
 * We want to free the bitmap bits outside of any recovery context as
 * we'll need a cluster lock to do so, but we must clear the local
 * alloc before giving up the recovered nodes journal. To solve this,
 * we kmalloc a copy of the local alloc before it's change for the
 * caller to process with ocfs2_complete_local_alloc_recovery
 */
int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
				     int slot_num,
				     struct ocfs2_dinode **alloc_copy)
{
	int status = 0;
	struct buffer_head *alloc_bh = NULL;
	struct inode *inode = NULL;
	struct ocfs2_dinode *alloc;

	mlog_entry("(slot_num = %d)\n", slot_num);

	*alloc_copy = NULL;

	inode = ocfs2_get_system_file_inode(osb,
					    LOCAL_ALLOC_SYSTEM_INODE,
					    slot_num);
	if (!inode) {
		status = -EINVAL;
		mlog_errno(status);
		goto bail;
	}

	mutex_lock(&inode->i_mutex);

	status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
				  &alloc_bh, 0, inode);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	*alloc_copy = kmalloc(alloc_bh->b_size, GFP_KERNEL);
	if (!(*alloc_copy)) {
		status = -ENOMEM;
		goto bail;
	}
	memcpy((*alloc_copy), alloc_bh->b_data, alloc_bh->b_size);

	alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
	ocfs2_clear_local_alloc(alloc);

	status = ocfs2_write_block(osb, alloc_bh, inode);
	if (status < 0)
		mlog_errno(status);

bail:
	if ((status < 0) && (*alloc_copy)) {
		kfree(*alloc_copy);
		*alloc_copy = NULL;
	}

	if (alloc_bh)
		brelse(alloc_bh);

	if (inode) {
		mutex_unlock(&inode->i_mutex);
		iput(inode);
	}

	mlog_exit(status);
	return status;
}