Beispiel #1
0
static int ocfs2_readlink(struct dentry *dentry,
			  char __user *buffer,
			  int buflen)
{
	int ret;
	char *link;
	struct buffer_head *bh = NULL;
	struct inode *inode = dentry->d_inode;

	mlog_entry_void();

	link = ocfs2_fast_symlink_getlink(inode, &bh);
	if (IS_ERR(link)) {
		ret = PTR_ERR(link);
		goto out;
	}

	/*
	 * Without vfsmount we can't update atime now,
	 * but we will update atime here ultimately.
	 */
	ret = vfs_readlink(dentry, buffer, buflen, link);

	brelse(bh);
out:
	mlog_exit(ret);
	return ret;
}
Beispiel #2
0
/* will give out up to bits_wanted contiguous bits. */
static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
				     struct ocfs2_alloc_context *ac,
				     handle_t *handle,
				     u32 bits_wanted,
				     u32 min_bits,
				     u16 *bit_off,
				     unsigned int *num_bits,
				     u64 *bg_blkno)
{
	int status;
	u16 victim, i;
	u16 bits_left = 0;
	u64 hint_blkno = ac->ac_last_group;
	struct ocfs2_chain_list *cl;
	struct ocfs2_dinode *fe;

	mlog_entry_void();

	BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
	BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given));
	BUG_ON(!ac->ac_bh);

	fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;

	/* The bh was validated by the inode read during
	 * ocfs2_reserve_suballoc_bits().  Any corruption is a code bug. */
	BUG_ON(!OCFS2_IS_VALID_DINODE(fe));

	if (le32_to_cpu(fe->id1.bitmap1.i_used) >=
	    le32_to_cpu(fe->id1.bitmap1.i_total)) {
		ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used "
			    "bits but only %u total."
Beispiel #3
0
int ocfs2_getattr(struct vfsmount *mnt,
		  struct dentry *dentry,
		  struct kstat *stat)
{
	struct inode *inode = dentry->d_inode;
	struct super_block *sb = dentry->d_inode->i_sb;
	struct ocfs2_super *osb = sb->s_fs_info;
	int err;

	mlog_entry_void();

	err = ocfs2_inode_revalidate(dentry);
	if (err) {
		if (err != -ENOENT)
			mlog_errno(err);
		goto bail;
	}

	generic_fillattr(inode, stat);

	/* We set the blksize from the cluster size for performance */
	stat->blksize = osb->s_clustersize;

bail:
	mlog_exit(err);

	return err;
}
Beispiel #4
0
static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
				     struct inode *inode,
				     struct buffer_head *fe_bh)
{
	int status = 0;
	struct ocfs2_dinode *fe;
	handle_t *handle = NULL;

	mlog_entry_void();

	fe = (struct ocfs2_dinode *) fe_bh->b_data;

	/*
	 * This check will also skip truncate of inodes with inline
	 * data and fast symlinks.
	 */
	if (fe->i_clusters) {
		if (ocfs2_should_order_data(inode))
			ocfs2_begin_ordered_truncate(inode, 0);

		handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
		if (IS_ERR(handle)) {
			status = PTR_ERR(handle);
			handle = NULL;
			mlog_errno(status);
			goto out;
		}

		status = ocfs2_journal_access_di(handle, INODE_CACHE(inode),
						 fe_bh,
						 OCFS2_JOURNAL_ACCESS_WRITE);
		if (status < 0) {
			mlog_errno(status);
			goto out;
		}

		i_size_write(inode, 0);

		status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
		if (status < 0) {
			mlog_errno(status);
			goto out;
		}

		ocfs2_commit_trans(osb, handle);
		handle = NULL;

		status = ocfs2_commit_truncate(osb, inode, fe_bh);
		if (status < 0) {
			mlog_errno(status);
			goto out;
		}
	}

out:
	if (handle)
		ocfs2_commit_trans(osb, handle);
	mlog_exit(status);
	return status;
}
Beispiel #5
0
int ocfs2_update_inode_atime(struct inode *inode,
			     struct buffer_head *bh)
{
	int ret;
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	handle_t *handle;

	mlog_entry_void();

	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
	if (handle == NULL) {
		ret = -ENOMEM;
		mlog_errno(ret);
		goto out;
	}

	inode->i_atime = CURRENT_TIME;
	ret = ocfs2_mark_inode_dirty(handle, inode, bh);
	if (ret < 0)
		mlog_errno(ret);

	ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
out:
	mlog_exit(ret);
	return ret;
}
Beispiel #6
0
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
					struct buffer_head **bh)
{
	int status;
	char *link = NULL;
	struct ocfs2_dinode *fe;

	mlog_entry_void();

	status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
				  OCFS2_I(inode)->ip_blkno,
				  bh,
				  OCFS2_BH_CACHED,
				  inode);
	if (status < 0) {
		mlog_errno(status);
		link = ERR_PTR(status);
		goto bail;
	}

	fe = (struct ocfs2_dinode *) (*bh)->b_data;
	link = (char *) fe->id2.i_symlink;
bail:
	mlog_exit(status);

	return link;
}
Beispiel #7
0
int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
				 handle_t *handle,
				 struct ocfs2_alloc_context *ac,
				 u32 bits_wanted,
				 u32 *bit_off,
				 u32 *num_bits)
{
	int status, start;
	struct inode *local_alloc_inode;
	void *bitmap;
	struct ocfs2_dinode *alloc;
	struct ocfs2_local_alloc *la;

	mlog_entry_void();
	BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);

	local_alloc_inode = ac->ac_inode;
	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
	la = OCFS2_LOCAL_ALLOC(alloc);

	start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
	if (start == -1) {
		/* TODO: Shouldn't we just BUG here? */
		status = -ENOSPC;
		mlog_errno(status);
		goto bail;
	}

	bitmap = la->la_bitmap;
	*bit_off = le32_to_cpu(la->la_bm_off) + start;
	/* local alloc is always contiguous by nature -- we never
	 * delete bits from it! */
	*num_bits = bits_wanted;

	status = ocfs2_journal_access_di(handle,
					 INODE_CACHE(local_alloc_inode),
					 osb->local_alloc_bh,
					 OCFS2_JOURNAL_ACCESS_WRITE);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	while(bits_wanted--)
		ocfs2_set_bit(start++, bitmap);

	le32_add_cpu(&alloc->id1.bitmap1.i_used, *num_bits);

	status = ocfs2_journal_dirty(handle, osb->local_alloc_bh);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	status = 0;
bail:
	mlog_exit(status);
	return status;
}
Beispiel #8
0
static int ocfs2_block_group_fill(handle_t *handle,
				  struct inode *alloc_inode,
				  struct buffer_head *bg_bh,
				  u64 group_blkno,
				  u16 my_chain,
				  struct ocfs2_chain_list *cl)
{
	int status = 0;
	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
	struct super_block * sb = alloc_inode->i_sb;

	mlog_entry_void();

	if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) {
		ocfs2_error(alloc_inode->i_sb, "group block (%llu) != "
			    "b_blocknr (%llu)",
			    (unsigned long long)group_blkno,
			    (unsigned long long) bg_bh->b_blocknr);
		status = -EIO;
		goto bail;
	}

	status = ocfs2_journal_access(handle,
				      alloc_inode,
				      bg_bh,
				      OCFS2_JOURNAL_ACCESS_CREATE);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	memset(bg, 0, sb->s_blocksize);
	strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
	bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
	bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb));
	bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl));
	bg->bg_chain = cpu_to_le16(my_chain);
	bg->bg_next_group = cl->cl_recs[my_chain].c_blkno;
	bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno);
	bg->bg_blkno = cpu_to_le64(group_blkno);
	/* set the 1st bit in the bitmap to account for the descriptor block */
	ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap);
	bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1);

	status = ocfs2_journal_dirty(handle, bg_bh);
	if (status < 0)
		mlog_errno(status);

	/* There is no need to zero out or otherwise initialize the
	 * other blocks in a group - All valid FS metadata in a block
	 * group stores the superblock fs_generation value at
	 * allocation time. */

bail:
	mlog_exit(status);
	return status;
}
Beispiel #9
0
static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
				     struct inode *inode,
				     struct buffer_head *fe_bh,
				     u64 new_i_size)
{
	int status;
	handle_t *handle;
	struct ocfs2_dinode *di;

	mlog_entry_void();

	/* TODO: This needs to actually orphan the inode in this
	 * transaction. */

	handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
	if (IS_ERR(handle)) {
		status = PTR_ERR(handle);
		mlog_errno(status);
		goto out;
	}

	status = ocfs2_journal_access(handle, inode, fe_bh,
				      OCFS2_JOURNAL_ACCESS_WRITE);
	if (status < 0) {
		mlog_errno(status);
		goto out_commit;
	}

	/*
	 * Do this before setting i_size.
	 */
	status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size);
	if (status) {
		mlog_errno(status);
		goto out_commit;
	}

	i_size_write(inode, new_i_size);
	inode->i_blocks = ocfs2_align_bytes_to_sectors(new_i_size);
	inode->i_ctime = inode->i_mtime = CURRENT_TIME;

	di = (struct ocfs2_dinode *) fe_bh->b_data;
	di->i_size = cpu_to_le64(new_i_size);
	di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec);
	di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);

	status = ocfs2_journal_dirty(handle, fe_bh);
	if (status < 0)
		mlog_errno(status);

out_commit:
	ocfs2_commit_trans(osb, handle);
out:

	mlog_exit(status);
	return status;
}
Beispiel #10
0
/* Callers don't need to care which bitmap (local alloc or main) to
 * use so we figure it out for them, but unfortunately this clutters
 * things a bit. */
int ocfs2_reserve_clusters(struct ocfs2_super *osb,
			   u32 bits_wanted,
			   struct ocfs2_alloc_context **ac)
{
	int status;

	mlog_entry_void();

	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
	if (!(*ac)) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	(*ac)->ac_bits_wanted = bits_wanted;

	status = -ENOSPC;
	if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
		status = ocfs2_reserve_local_alloc_bits(osb,
							bits_wanted,
							*ac);
		if ((status < 0) && (status != -ENOSPC)) {
			mlog_errno(status);
			goto bail;
		} else if (status == -ENOSPC) {
			/* reserve_local_bits will return enospc with
			 * the local alloc inode still locked, so we
			 * can change this safely here. */
			mlog(0, "Disabling local alloc\n");
			/* We set to OCFS2_LA_DISABLED so that umount
			 * can clean up what's left of the local
			 * allocation */
			osb->local_alloc_state = OCFS2_LA_DISABLED;
		}
	}

	if (status == -ENOSPC) {
		status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
		if (status < 0) {
			if (status != -ENOSPC)
				mlog_errno(status);
			goto bail;
		}
	}

	status = 0;
bail:
	if ((status < 0) && *ac) {
		ocfs2_free_alloc_context(*ac);
		*ac = NULL;
	}

	mlog_exit(status);
	return status;
}
Beispiel #11
0
void dlm_do_local_bast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
		       struct dlm_lock *lock, int blocked_type)
{
	dlm_bastlockfunc_t *fn = lock->bast;

	mlog_entry_void();
	BUG_ON(lock->ml.node != dlm->node_num);

	(*fn)(lock->astdata, blocked_type);
}
Beispiel #12
0
void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
{
	mlog_entry_void();

	BUG_ON(!dlm);
	BUG_ON(!lock);

	spin_lock(&dlm->ast_lock);
	__dlm_queue_bast(dlm, lock);
	spin_unlock(&dlm->ast_lock);
}
Beispiel #13
0
/* Callers don't need to care which bitmap (local alloc or main) to
 * use so we figure it out for them, but unfortunately this clutters
 * things a bit. */
static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb,
					     u32 bits_wanted, u64 max_block,
					     int flags,
					     struct ocfs2_alloc_context **ac)
{
	int status;

	mlog_entry_void();

	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
	if (!(*ac)) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	(*ac)->ac_bits_wanted = bits_wanted;
	(*ac)->ac_max_block = max_block;

	status = -ENOSPC;
	if (!(flags & ALLOC_GROUPS_FROM_GLOBAL) &&
	    ocfs2_alloc_should_use_local(osb, bits_wanted)) {
		status = ocfs2_reserve_local_alloc_bits(osb,
							bits_wanted,
							*ac);
		if (status == -EFBIG) {
			/* The local alloc window is outside ac_max_block.
			 * use the main bitmap. */
			status = -ENOSPC;
		} else if ((status < 0) && (status != -ENOSPC)) {
			mlog_errno(status);
			goto bail;
		}
	}

	if (status == -ENOSPC) {
		status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
		if (status < 0) {
			if (status != -ENOSPC)
				mlog_errno(status);
			goto bail;
		}
	}

	status = 0;
bail:
	if ((status < 0) && *ac) {
		ocfs2_free_alloc_context(*ac);
		*ac = NULL;
	}

	mlog_exit(status);
	return status;
}
/*
 * pass it the bitmap lock in lock_bh if you have it.
 */
static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
					struct ocfs2_journal_handle *handle,
					struct ocfs2_alloc_context *ac)
{
	int status = 0;
	u32 cluster_off, cluster_count;
	struct ocfs2_dinode *alloc = NULL;
	struct ocfs2_local_alloc *la;

	mlog_entry_void();

	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
	la = OCFS2_LOCAL_ALLOC(alloc);

	if (alloc->id1.bitmap1.i_total)
		mlog(0, "asking me to alloc a new window over a non-empty "
		     "one\n");

	mlog(0, "Allocating %u clusters for a new window.\n",
	     ocfs2_local_alloc_window_bits(osb));
	/* we used the generic suballoc reserve function, but we set
	 * everything up nicely, so there's no reason why we can't use
	 * the more specific cluster api to claim bits. */
	status = ocfs2_claim_clusters(osb, handle, ac,
				      ocfs2_local_alloc_window_bits(osb),
				      &cluster_off, &cluster_count);
	if (status < 0) {
		if (status != -ENOSPC)
			mlog_errno(status);
		goto bail;
	}

	la->la_bm_off = cpu_to_le32(cluster_off);
	alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count);
	/* just in case... In the future when we find space ourselves,
	 * we don't have to get all contiguous -- but we'll have to
	 * set all previously used bits in bitmap and update
	 * la_bits_set before setting the bits in the main bitmap. */
	alloc->id1.bitmap1.i_used = 0;
	memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0,
	       le16_to_cpu(la->la_size));

	mlog(0, "New window allocated:\n");
	mlog(0, "window la_bm_off = %u\n",
	     OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
	mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total));

bail:
	mlog_exit(status);
	return status;
}
Beispiel #15
0
static inline int ocfs2_block_group_clear_bits(handle_t *handle,
					       struct inode *alloc_inode,
					       struct ocfs2_group_desc *bg,
					       struct buffer_head *group_bh,
					       unsigned int bit_off,
					       unsigned int num_bits)
{
	int status;
	unsigned int tmp;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
	struct ocfs2_group_desc *undo_bg = NULL;

	mlog_entry_void();

	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
		status = -EIO;
		goto bail;
	}

	mlog(0, "off = %u, num = %u\n", bit_off, num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access(handle, alloc_inode, group_bh,
				      journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		undo_bg = (struct ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data;

	tmp = num_bits;
	while(tmp--) {
		ocfs2_clear_bit((bit_off + tmp),
				(unsigned long *) bg->bg_bitmap);
		if (ocfs2_is_cluster_bitmap(alloc_inode))
			ocfs2_set_bit(bit_off + tmp,
				      (unsigned long *) undo_bg->bg_bitmap);
	}
	le16_add_cpu(&bg->bg_free_bits_count, num_bits);

	status = ocfs2_journal_dirty(handle, group_bh);
	if (status < 0)
		mlog_errno(status);
bail:
	return status;
}
Beispiel #16
0
static inline int ocfs2_block_group_set_bits(handle_t *handle,
					     struct inode *alloc_inode,
					     struct ocfs2_group_desc *bg,
					     struct buffer_head *group_bh,
					     unsigned int bit_off,
					     unsigned int num_bits)
{
	int status;
	void *bitmap = bg->bg_bitmap;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;

	mlog_entry_void();

	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
		status = -EIO;
		goto bail;
	}
	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);

	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
	     num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access(handle,
				      alloc_inode,
				      group_bh,
				      journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);

	while(num_bits--)
		ocfs2_set_bit(bit_off++, bitmap);

	status = ocfs2_journal_dirty(handle,
				     group_bh);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

bail:
	mlog_exit(status);
	return status;
}
Beispiel #17
0
/*
 * JBD Might read a cached version of another nodes journal file. We
 * don't want this as this file changes often and we get no
 * notification on those changes. The only way to be sure that we've
 * got the most up to date version of those blocks then is to force
 * read them off disk. Just searching through the buffer cache won't
 * work as there may be pages backing this file which are still marked
 * up to date. We know things can't change on this file underneath us
 * as we have the lock by now :)
 */
static int ocfs2_force_read_journal(struct inode *inode)
{
	int status = 0;
	int i;
	u64 v_blkno, p_blkno, p_blocks, num_blocks;
#define CONCURRENT_JOURNAL_FILL 32ULL
	struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL];

	mlog_entry_void();

	memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL);

	num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size);
	v_blkno = 0;
	while (v_blkno < num_blocks) {
		status = ocfs2_extent_map_get_blocks(inode, v_blkno,
						     &p_blkno, &p_blocks, NULL);
		if (status < 0) {
			mlog_errno(status);
			goto bail;
		}

		if (p_blocks > CONCURRENT_JOURNAL_FILL)
			p_blocks = CONCURRENT_JOURNAL_FILL;

		/* We are reading journal data which should not
		 * be put in the uptodate cache */
		status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
					   p_blkno, p_blocks, bhs, 0,
					   NULL);
		if (status < 0) {
			mlog_errno(status);
			goto bail;
		}

		for(i = 0; i < p_blocks; i++) {
			brelse(bhs[i]);
			bhs[i] = NULL;
		}

		v_blkno += p_blocks;
	}

bail:
	for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++)
		if (bhs[i])
			brelse(bhs[i]);
	mlog_exit(status);
	return status;
}
static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc)
{
	struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
	int i;
	mlog_entry_void();

	alloc->id1.bitmap1.i_total = 0;
	alloc->id1.bitmap1.i_used = 0;
	la->la_bm_off = 0;
	for(i = 0; i < le16_to_cpu(la->la_size); i++)
		la->la_bitmap[i] = 0;

	mlog_exit_void();
}
Beispiel #19
0
static inline int ocfs2_block_group_set_bits(handle_t *handle,
					     struct inode *alloc_inode,
					     struct ocfs2_group_desc *bg,
					     struct buffer_head *group_bh,
					     unsigned int bit_off,
					     unsigned int num_bits)
{
	int status;
	void *bitmap = bg->bg_bitmap;
	int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;

	mlog_entry_void();

	/* All callers get the descriptor via
	 * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
	BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
	BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);

	mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
	     num_bits);

	if (ocfs2_is_cluster_bitmap(alloc_inode))
		journal_type = OCFS2_JOURNAL_ACCESS_UNDO;

	status = ocfs2_journal_access_gd(handle,
					 INODE_CACHE(alloc_inode),
					 group_bh,
					 journal_type);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	le16_add_cpu(&bg->bg_free_bits_count, -num_bits);

	while(num_bits--)
		ocfs2_set_bit(bit_off++, bitmap);

	status = ocfs2_journal_dirty(handle,
				     group_bh);
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

bail:
	mlog_exit(status);
	return status;
}
Beispiel #20
0
void dlm_do_local_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
		      struct dlm_lock *lock)
{
	dlm_astlockfunc_t *fn;
	struct dlm_lockstatus *lksb;

	mlog_entry_void();

	lksb = lock->lksb;
	fn = lock->ast;
	BUG_ON(lock->ml.node != dlm->node_num);

	dlm_update_lvb(dlm, res, lock);
	(*fn)(lock->astdata);
}
Beispiel #21
0
/* Called under inode_lock, with no more references on the
 * struct inode, so it's safe here to check the flags field
 * and to manipulate i_nlink without any other locks. */
void ocfs2_drop_inode(struct inode *inode)
{
	struct ocfs2_inode_info *oi = OCFS2_I(inode);

	mlog_entry_void();

	mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n",
	     (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags);

	if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED)
		generic_delete_inode(inode);
	else
		generic_drop_inode(inode);

	mlog_exit_void();
}
static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
{
	int i;
	u8 *buffer;
	u32 count = 0;
	struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);

	mlog_entry_void();

	buffer = la->la_bitmap;
	for (i = 0; i < le16_to_cpu(la->la_size); i++)
		count += hweight8(buffer[i]);

	mlog_exit(count);
	return count;
}
int ocfs2_find_slot(struct ocfs2_super *osb)
{
	int status;
	s16 slot;
	struct ocfs2_slot_info *si;

	mlog_entry_void();

	si = osb->slot_info;

	ocfs2_update_slot_info(si);

	spin_lock(&si->si_lock);
	/* search for ourselves first and take the slot if it already
	 * exists. Perhaps we need to mark this in a variable for our
	 * own journal recovery? Possibly not, though we certainly
	 * need to warn to the user */
	slot = __ocfs2_node_num_to_slot(si, osb->node_num);
	if (slot == OCFS2_INVALID_SLOT) {
		/* if no slot yet, then just take 1st available
		 * one. */
		slot = __ocfs2_find_empty_slot(si);
		if (slot == OCFS2_INVALID_SLOT) {
			spin_unlock(&si->si_lock);
			mlog(ML_ERROR, "no free slots available!\n");
			status = -EINVAL;
			goto bail;
		}
	} else
		mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
		     slot);

	__ocfs2_fill_slot(si, slot, osb->node_num);
	osb->slot_num = slot;
	spin_unlock(&si->si_lock);

	mlog(0, "taking node slot %d\n", osb->slot_num);

	status = ocfs2_update_disk_slots(osb, si);
	if (status < 0)
		mlog_errno(status);

bail:
	mlog_exit(status);
	return status;
}
Beispiel #24
0
static int ocfs2_commit_cache(struct ocfs2_super *osb)
{
	int status = 0;
	unsigned int flushed;
	unsigned long old_id;
	struct ocfs2_journal *journal = NULL;

	mlog_entry_void();

	journal = osb->journal;

	/* Flush all pending commits and checkpoint the journal. */
	down_write(&journal->j_trans_barrier);

	if (atomic_read(&journal->j_num_trans) == 0) {
		up_write(&journal->j_trans_barrier);
		mlog(0, "No transactions for me to flush!\n");
		goto finally;
	}

	journal_lock_updates(journal->j_journal);
	status = journal_flush(journal->j_journal);
	journal_unlock_updates(journal->j_journal);
	if (status < 0) {
		up_write(&journal->j_trans_barrier);
		mlog_errno(status);
		goto finally;
	}

	old_id = ocfs2_inc_trans_id(journal);

	flushed = atomic_read(&journal->j_num_trans);
	atomic_set(&journal->j_num_trans, 0);
	up_write(&journal->j_trans_barrier);

	mlog(0, "commit_thread: flushed transaction %lu (%u handles)\n",
	     journal->j_trans_id, flushed);

	ocfs2_wake_downconvert_thread(osb);
	wake_up(&journal->j_checkpointed);
finally:
	mlog_exit(status);
	return status;
}
static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
{
	mlog_entry_void();

	BUG_ON(!dlm);
	BUG_ON(!lock);

	assert_spin_locked(&dlm->ast_lock);
	if (!list_empty(&lock->ast_list)) {
		mlog(ML_ERROR, "ast list not empty!!  pending=%d, newlevel=%d\n",
		     lock->ast_pending, lock->ml.type);
		BUG();
	}
	BUG_ON(!list_empty(&lock->ast_list));
	if (lock->ast_pending)
		mlog(0, "lock has an ast getting flushed right now\n");

	/* putting lock on list, add a ref */
	dlm_lock_get(lock);
	spin_lock(&lock->spinlock);

	/* check to see if this ast obsoletes the bast */
	if (dlm_should_cancel_bast(dlm, lock)) {
		struct dlm_lock_resource *res = lock->lockres;
		mlog(0, "%s: cancelling bast for %.*s\n",
		     dlm->name, res->lockname.len, res->lockname.name);
		lock->bast_pending = 0;
		list_del_init(&lock->bast_list);
		lock->ml.highest_blocked = LKM_IVMODE;
		/* removing lock from list, remove a ref.  guaranteed
		 * this won't be the last ref because of the get above,
		 * so res->spinlock will not be taken here */
		dlm_lock_put(lock);
		/* free up the reserved bast that we are cancelling.
		 * guaranteed that this will not be the last reserved
		 * ast because *both* an ast and a bast were reserved 
		 * to get to this point.  the res->spinlock will not be
		 * taken here */
		dlm_lockres_release_ast(dlm, res);
	}
	list_add_tail(&lock->ast_list, &dlm->pending_asts);
	lock->ast_pending = 1;
	spin_unlock(&lock->spinlock);
}
Beispiel #26
0
static void __dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
{
	mlog_entry_void();

	BUG_ON(!dlm);
	BUG_ON(!lock);
	assert_spin_locked(&dlm->ast_lock);

	BUG_ON(!list_empty(&lock->bast_list));
	if (lock->bast_pending)
		mlog(0, "lock has a bast getting flushed right now\n");

	/* putting lock on list, add a ref */
	dlm_lock_get(lock);
	spin_lock(&lock->spinlock);
	list_add_tail(&lock->bast_list, &dlm->pending_basts);
	lock->bast_pending = 1;
	spin_unlock(&lock->spinlock);
}
Beispiel #27
0
int ocfs2_journal_load(struct ocfs2_journal *journal, int local)
{
	int status = 0;
	struct ocfs2_super *osb;

	mlog_entry_void();

	BUG_ON(!journal);

	osb = journal->j_osb;

	status = journal_load(journal->j_journal);
	if (status < 0) {
		mlog(ML_ERROR, "Failed to load journal!\n");
		goto done;
	}

	ocfs2_clear_journal_error(osb->sb, journal->j_journal, osb->slot_num);

	status = ocfs2_journal_toggle_dirty(osb, 1);
	if (status < 0) {
		mlog_errno(status);
		goto done;
	}

	/* Launch the commit thread */
	if (!local) {
		osb->commit_task = kthread_run(ocfs2_commit_thread, osb,
					       "ocfs2cmt");
		if (IS_ERR(osb->commit_task)) {
			status = PTR_ERR(osb->commit_task);
			osb->commit_task = NULL;
			mlog(ML_ERROR, "unable to launch ocfs2commit thread, "
			     "error=%d", status);
			goto done;
		}
	} else
		osb->commit_task = NULL;

done:
	mlog_exit(status);
	return status;
}
Beispiel #28
0
int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd)
{
	int ret;

	mlog_entry_void();

	ret = ocfs2_meta_lock(inode, NULL, 0);
	if (ret) {
		if (ret != -ENOENT)
			mlog_errno(ret);
		goto out;
	}

	ret = generic_permission(inode, mask, NULL);

	ocfs2_meta_unlock(inode, 0);
out:
	mlog_exit(ret);
	return ret;
}
Beispiel #29
0
int dlm_do_remote_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
		      struct dlm_lock *lock)
{
	int ret;
	struct dlm_lockstatus *lksb;
	int lksbflags;

	mlog_entry_void();

	lksb = lock->lksb;
	BUG_ON(lock->ml.node == dlm->node_num);

	lksbflags = lksb->flags;
	dlm_update_lvb(dlm, res, lock);

	/* lock request came from another node
	 * go do the ast over there */
	ret = dlm_send_proxy_ast(dlm, res, lock, lksbflags);
	return ret;
}
Beispiel #30
0
int ocfs2_free_clusters(handle_t *handle,
		       struct inode *bitmap_inode,
		       struct buffer_head *bitmap_bh,
		       u64 start_blk,
		       unsigned int num_clusters)
{
	int status;
	u16 bg_start_bit;
	u64 bg_blkno;
	struct ocfs2_dinode *fe;

	/* You can't ever have a contiguous set of clusters
	 * bigger than a block group bitmap so we never have to worry
	 * about looping on them. */

	mlog_entry_void();

	/* This is expensive. We can safely remove once this stuff has
	 * gotten tested really well. */
	BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk)));

	fe = (struct ocfs2_dinode *) bitmap_bh->b_data;

	ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
				     &bg_start_bit);

	mlog(0, "want to free %u clusters starting at block %llu\n",
	     num_clusters, (unsigned long long)start_blk);
	mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n",
	     (unsigned long long)bg_blkno, bg_start_bit);

	status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
					  bg_start_bit, bg_blkno,
					  num_clusters);
	if (status < 0)
		mlog_errno(status);

	mlog_exit(status);
	return status;
}