Skip to content

Commit

Permalink
ocfs2: Add quota calls for allocation and freeing of inodes and space
Browse files Browse the repository at this point in the history
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: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
  • Loading branch information
Jan Kara authored and Mark Fasheh committed Jan 5, 2009
1 parent 9e33d69 commit a90714c
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 39 deletions.
20 changes: 18 additions & 2 deletions fs/ocfs2/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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:
Expand Down
16 changes: 13 additions & 3 deletions fs/ocfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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.
Expand All @@ -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;
}

/*
Expand All @@ -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)
Expand All @@ -1770,6 +1776,10 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
*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);

Expand Down
24 changes: 22 additions & 2 deletions fs/ocfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
72 changes: 67 additions & 5 deletions fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -57,6 +58,7 @@
#include "super.h"
#include "xattr.h"
#include "acl.h"
#include "quota.h"

#include "buffer_head_io.h"

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -577,6 +580,13 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
}

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. */
Expand Down Expand Up @@ -614,6 +624,10 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
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) {
Expand Down Expand Up @@ -646,6 +660,9 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -947,11 +967,47 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
}
}

handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
mlog_errno(status);
goto bail_unlock;
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;
}
}

/*
Expand All @@ -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)
Expand Down
10 changes: 8 additions & 2 deletions fs/ocfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/quotaops.h>

#include <asm/byteorder.h>

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit a90714c

Please sign in to comment.