Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a90714c1 authored by Jan Kara's avatar Jan Kara Committed by Mark Fasheh
Browse files

ocfs2: Add quota calls for allocation and freeing of inodes and space



Add quota calls for allocation and freeing of inodes and space, also update
estimates on number of needed credits for a transaction. Move out inode
allocation from ocfs2_mknod_locked() because vfs_dq_init() must be called
outside of a transaction.

Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent 9e33d69f
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/swap.h>
#include <linux/quotaops.h>

#define MLOG_MASK_PREFIX ML_DISK_ALLOC
#include <cluster/masklog.h>
@@ -5322,7 +5323,7 @@ int ocfs2_remove_btree_range(struct inode *inode,
		}
	}

	handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS);
	handle = ocfs2_start_trans(osb, ocfs2_remove_extent_credits(osb->sb));
	if (IS_ERR(handle)) {
		ret = PTR_ERR(handle);
		mlog_errno(ret);
@@ -6552,6 +6553,8 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
		goto bail;
	}

	vfs_dq_free_space_nodirty(inode,
			ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
	spin_lock(&OCFS2_I(inode)->ip_lock);
	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
				      clusters_to_del;
@@ -6860,6 +6863,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
	struct page **pages = NULL;
	loff_t end = osb->s_clustersize;
	struct ocfs2_extent_tree et;
	int did_quota = 0;

	has_data = i_size_read(inode) ? 1 : 0;

@@ -6879,7 +6883,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
		}
	}

	handle = ocfs2_start_trans(osb, OCFS2_INLINE_TO_EXTENTS_CREDITS);
	handle = ocfs2_start_trans(osb,
				   ocfs2_inline_to_extents_credits(osb->sb));
	if (IS_ERR(handle)) {
		ret = PTR_ERR(handle);
		mlog_errno(ret);
@@ -6898,6 +6903,13 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
		unsigned int page_end;
		u64 phys;

		if (vfs_dq_alloc_space_nodirty(inode,
				       ocfs2_clusters_to_bytes(osb->sb, 1))) {
			ret = -EDQUOT;
			goto out_commit;
		}
		did_quota = 1;

		ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
					   &num);
		if (ret) {
@@ -6971,6 +6983,10 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
	}

out_commit:
	if (ret < 0 && did_quota)
		vfs_dq_free_space_nodirty(inode,
					  ocfs2_clusters_to_bytes(osb->sb, 1));

	ocfs2_commit_trans(osb, handle);

out_unlock:
+13 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/swap.h>
#include <linux/pipe_fs_i.h>
#include <linux/mpage.h>
#include <linux/quotaops.h>

#define MLOG_MASK_PREFIX ML_FILE_IO
#include <cluster/masklog.h>
@@ -1730,6 +1731,11 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,

	wc->w_handle = handle;

	if (clusters_to_alloc && vfs_dq_alloc_space_nodirty(inode,
			ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc))) {
		ret = -EDQUOT;
		goto out_commit;
	}
	/*
	 * We don't want this to fail in ocfs2_write_end(), so do it
	 * here.
@@ -1738,7 +1744,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
				   OCFS2_JOURNAL_ACCESS_WRITE);
	if (ret) {
		mlog_errno(ret);
		goto out_commit;
		goto out_quota;
	}

	/*
@@ -1751,14 +1757,14 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
					 mmap_page);
	if (ret) {
		mlog_errno(ret);
		goto out_commit;
		goto out_quota;
	}

	ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
					  len);
	if (ret) {
		mlog_errno(ret);
		goto out_commit;
		goto out_quota;
	}

	if (data_ac)
@@ -1770,6 +1776,10 @@ success:
	*pagep = wc->w_target_page;
	*fsdata = wc;
	return 0;
out_quota:
	if (clusters_to_alloc)
		vfs_dq_free_space(inode,
			  ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
out_commit:
	ocfs2_commit_trans(osb, handle);

+22 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/quotaops.h>

#define MLOG_MASK_PREFIX ML_NAMEI
#include <cluster/masklog.h>
@@ -1210,9 +1211,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
				   unsigned int blocks_wanted,
				   struct buffer_head **first_block_bh)
{
	int ret, credits = OCFS2_INLINE_TO_EXTENTS_CREDITS;
	u32 alloc, bit_off, len;
	struct super_block *sb = dir->i_sb;
	int ret, credits = ocfs2_inline_to_extents_credits(sb);
	u64 blkno, bytes = blocks_wanted << sb->s_blocksize_bits;
	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
	struct ocfs2_inode_info *oi = OCFS2_I(dir);
@@ -1221,6 +1222,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
	handle_t *handle;
	struct ocfs2_extent_tree et;
	int did_quota = 0;

	ocfs2_init_dinode_extent_tree(&et, dir, di_bh);

@@ -1258,6 +1260,12 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
		goto out_sem;
	}

	if (vfs_dq_alloc_space_nodirty(dir,
				ocfs2_clusters_to_bytes(osb->sb, alloc))) {
		ret = -EDQUOT;
		goto out_commit;
	}
	did_quota = 1;
	/*
	 * Try to claim as many clusters as the bitmap can give though
	 * if we only get one now, that's enough to continue. The rest
@@ -1380,6 +1388,9 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
	dirdata_bh = NULL;

out_commit:
	if (ret < 0 && did_quota)
		vfs_dq_free_space_nodirty(dir,
			ocfs2_clusters_to_bytes(osb->sb, 2));
	ocfs2_commit_trans(osb, handle);

out_sem:
@@ -1404,7 +1415,7 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
			       struct buffer_head **new_bh)
{
	int status;
	int extend;
	int extend, did_quota = 0;
	u64 p_blkno, v_blkno;

	spin_lock(&OCFS2_I(dir)->ip_lock);
@@ -1414,6 +1425,13 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
	if (extend) {
		u32 offset = OCFS2_I(dir)->ip_clusters;

		if (vfs_dq_alloc_space_nodirty(dir,
					ocfs2_clusters_to_bytes(sb, 1))) {
			status = -EDQUOT;
			goto bail;
		}
		did_quota = 1;

		status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
					      1, 0, parent_fe_bh, handle,
					      data_ac, meta_ac, NULL);
@@ -1439,6 +1457,8 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
	}
	status = 0;
bail:
	if (did_quota && status < 0)
		vfs_dq_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
	mlog_exit(status);
	return status;
}
+67 −5
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/mount.h>
#include <linux/writeback.h>
#include <linux/falloc.h>
#include <linux/quotaops.h>

#define MLOG_MASK_PREFIX ML_INODE
#include <cluster/masklog.h>
@@ -57,6 +58,7 @@
#include "super.h"
#include "xattr.h"
#include "acl.h"
#include "quota.h"

#include "buffer_head_io.h"

@@ -534,6 +536,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
	enum ocfs2_alloc_restarted why;
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct ocfs2_extent_tree et;
	int did_quota = 0;

	mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);

@@ -577,6 +580,13 @@ restart_all:
	}

restarted_transaction:
	if (vfs_dq_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb,
	    clusters_to_add))) {
		status = -EDQUOT;
		goto leave;
	}
	did_quota = 1;

	/* reserve a write to the file entry early on - that we if we
	 * run out of credits in the allocation path, we can still
	 * update i_size. */
@@ -614,6 +624,10 @@ restarted_transaction:
	spin_lock(&OCFS2_I(inode)->ip_lock);
	clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters);
	spin_unlock(&OCFS2_I(inode)->ip_lock);
	/* Release unused quota reservation */
	vfs_dq_free_space(inode,
			ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
	did_quota = 0;

	if (why != RESTART_NONE && clusters_to_add) {
		if (why == RESTART_META) {
@@ -646,6 +660,9 @@ restarted_transaction:
	     OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode));

leave:
	if (status < 0 && did_quota)
		vfs_dq_free_space(inode,
			ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
	if (handle) {
		ocfs2_commit_trans(osb, handle);
		handle = NULL;
@@ -877,6 +894,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
	struct ocfs2_super *osb = OCFS2_SB(sb);
	struct buffer_head *bh = NULL;
	handle_t *handle = NULL;
	int locked[MAXQUOTAS] = {0, 0};
	int credits, qtype;
	struct ocfs2_mem_dqinfo *oinfo;

	mlog_entry("(0x%p, '%.*s')\n", dentry,
	           dentry->d_name.len, dentry->d_name.name);
@@ -947,12 +967,48 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
		}
	}

	if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
	    (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
		credits = OCFS2_INODE_UPDATE_CREDITS;
		if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
		    && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
		    OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
			oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv;
			status = ocfs2_lock_global_qf(oinfo, 1);
			if (status < 0)
				goto bail_unlock;
			credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) +
				ocfs2_calc_qdel_credits(sb, USRQUOTA);
			locked[USRQUOTA] = 1;
		}
		if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
		    && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
		    OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
			oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv;
			status = ocfs2_lock_global_qf(oinfo, 1);
			if (status < 0)
				goto bail_unlock;
			credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) +
				   ocfs2_calc_qdel_credits(sb, GRPQUOTA);
			locked[GRPQUOTA] = 1;
		}
		handle = ocfs2_start_trans(osb, credits);
		if (IS_ERR(handle)) {
			status = PTR_ERR(handle);
			mlog_errno(status);
			goto bail_unlock;
		}
		status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
		if (status < 0)
			goto bail_commit;
	} else {
		handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
		if (IS_ERR(handle)) {
			status = PTR_ERR(handle);
			mlog_errno(status);
			goto bail_unlock;
		}
	}

	/*
	 * This will intentionally not wind up calling vmtruncate(),
@@ -974,6 +1030,12 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
bail_commit:
	ocfs2_commit_trans(osb, handle);
bail_unlock:
	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
		if (!locked[qtype])
			continue;
		oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
		ocfs2_unlock_global_qf(oinfo, 1);
	}
	ocfs2_inode_unlock(inode, 1);
bail_unlock_rw:
	if (size_change)
+8 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/quotaops.h>

#include <asm/byteorder.h>

@@ -603,7 +604,8 @@ static int ocfs2_remove_inode(struct inode *inode,
		goto bail;
	}

	handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS);
	handle = ocfs2_start_trans(osb, OCFS2_DELETE_INODE_CREDITS +
					ocfs2_quota_trans_credits(inode->i_sb));
	if (IS_ERR(handle)) {
		status = PTR_ERR(handle);
		mlog_errno(status);
@@ -635,6 +637,7 @@ static int ocfs2_remove_inode(struct inode *inode,
	}

	ocfs2_remove_from_cache(inode, di_bh);
	vfs_dq_free_inode(inode);

	status = ocfs2_free_dinode(handle, inode_alloc_inode,
				   inode_alloc_bh, di);
@@ -917,7 +920,10 @@ void ocfs2_delete_inode(struct inode *inode)

	mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);

	if (is_bad_inode(inode)) {
	/* When we fail in read_inode() we mark inode as bad. The second test
	 * catches the case when inode allocation fails before allocating
	 * a block for inode. */
	if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) {
		mlog(0, "Skipping delete of bad inode\n");
		goto bail;
	}
Loading