[Ocfs2-devel] [PATCH 26/29] ocfs2: Add quota calls for allocation and freeing of inodes and space
Mark Fasheh
mfasheh at suse.com
Wed Nov 5 16:06:29 PST 2008
On Sat, Oct 25, 2008 at 12:08:19AM +0200, Jan Kara wrote:
> diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
> index 9af16e0..75cdb0e 100644
> --- a/fs/ocfs2/file.c
> +++ b/fs/ocfs2/file.c
> @@ -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>
> @@ -56,6 +57,7 @@
> #include "suballoc.h"
> #include "super.h"
> #include "xattr.h"
> +#include "quota.h"
>
> #include "buffer_head_io.h"
>
> @@ -536,6 +538,8 @@ 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;
> + u32 total_clusters = clusters_to_add;
> + int did_quota = 0;
>
> mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
>
> @@ -584,6 +588,12 @@ restart_all:
> goto leave;
> }
>
> + if (!did_quota && vfs_dq_alloc_space_nodirty(inode,
> + ocfs2_clusters_to_bytes(osb->sb, total_clusters))) {
> + status = -EDQUOT;
> + goto leave;
> + }
> + did_quota = 1;
> restarted_transaction:
> /* reserve a write to the file entry early on - that we if we
> * run out of credits in the allocation path, we can still
> @@ -654,6 +664,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, total_clusters));
Shouldn't you subtract clusters_to_add clusters instead of total_clusters
here? In theory, we could have allocated *some* of the inode but failed
during a later pass.
> @@ -956,11 +972,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;
Ok, so this will all cause syncing on the global quota file because we need
to transfer one record to/from another? Is there any better way?
Rest of the patch looks great btw.
--Mark
--
Mark Fasheh
More information about the Ocfs2-devel
mailing list