diff options
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 372d96505a79..9374d374a264 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
36 | #include <linux/writeback.h> | 36 | #include <linux/writeback.h> |
37 | #include <linux/falloc.h> | 37 | #include <linux/falloc.h> |
38 | #include <linux/quotaops.h> | ||
38 | 39 | ||
39 | #define MLOG_MASK_PREFIX ML_INODE | 40 | #define MLOG_MASK_PREFIX ML_INODE |
40 | #include <cluster/masklog.h> | 41 | #include <cluster/masklog.h> |
@@ -57,6 +58,7 @@ | |||
57 | #include "super.h" | 58 | #include "super.h" |
58 | #include "xattr.h" | 59 | #include "xattr.h" |
59 | #include "acl.h" | 60 | #include "acl.h" |
61 | #include "quota.h" | ||
60 | 62 | ||
61 | #include "buffer_head_io.h" | 63 | #include "buffer_head_io.h" |
62 | 64 | ||
@@ -534,6 +536,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, | |||
534 | enum ocfs2_alloc_restarted why; | 536 | enum ocfs2_alloc_restarted why; |
535 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 537 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
536 | struct ocfs2_extent_tree et; | 538 | struct ocfs2_extent_tree et; |
539 | int did_quota = 0; | ||
537 | 540 | ||
538 | mlog_entry("(clusters_to_add = %u)\n", clusters_to_add); | 541 | mlog_entry("(clusters_to_add = %u)\n", clusters_to_add); |
539 | 542 | ||
@@ -577,6 +580,13 @@ restart_all: | |||
577 | } | 580 | } |
578 | 581 | ||
579 | restarted_transaction: | 582 | restarted_transaction: |
583 | if (vfs_dq_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb, | ||
584 | clusters_to_add))) { | ||
585 | status = -EDQUOT; | ||
586 | goto leave; | ||
587 | } | ||
588 | did_quota = 1; | ||
589 | |||
580 | /* reserve a write to the file entry early on - that we if we | 590 | /* reserve a write to the file entry early on - that we if we |
581 | * run out of credits in the allocation path, we can still | 591 | * run out of credits in the allocation path, we can still |
582 | * update i_size. */ | 592 | * update i_size. */ |
@@ -614,6 +624,10 @@ restarted_transaction: | |||
614 | spin_lock(&OCFS2_I(inode)->ip_lock); | 624 | spin_lock(&OCFS2_I(inode)->ip_lock); |
615 | clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters); | 625 | clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters); |
616 | spin_unlock(&OCFS2_I(inode)->ip_lock); | 626 | spin_unlock(&OCFS2_I(inode)->ip_lock); |
627 | /* Release unused quota reservation */ | ||
628 | vfs_dq_free_space(inode, | ||
629 | ocfs2_clusters_to_bytes(osb->sb, clusters_to_add)); | ||
630 | did_quota = 0; | ||
617 | 631 | ||
618 | if (why != RESTART_NONE && clusters_to_add) { | 632 | if (why != RESTART_NONE && clusters_to_add) { |
619 | if (why == RESTART_META) { | 633 | if (why == RESTART_META) { |
@@ -646,6 +660,9 @@ restarted_transaction: | |||
646 | OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode)); | 660 | OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode)); |
647 | 661 | ||
648 | leave: | 662 | leave: |
663 | if (status < 0 && did_quota) | ||
664 | vfs_dq_free_space(inode, | ||
665 | ocfs2_clusters_to_bytes(osb->sb, clusters_to_add)); | ||
649 | if (handle) { | 666 | if (handle) { |
650 | ocfs2_commit_trans(osb, handle); | 667 | ocfs2_commit_trans(osb, handle); |
651 | handle = NULL; | 668 | handle = NULL; |
@@ -877,6 +894,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
877 | struct ocfs2_super *osb = OCFS2_SB(sb); | 894 | struct ocfs2_super *osb = OCFS2_SB(sb); |
878 | struct buffer_head *bh = NULL; | 895 | struct buffer_head *bh = NULL; |
879 | handle_t *handle = NULL; | 896 | handle_t *handle = NULL; |
897 | int locked[MAXQUOTAS] = {0, 0}; | ||
898 | int credits, qtype; | ||
899 | struct ocfs2_mem_dqinfo *oinfo; | ||
880 | 900 | ||
881 | mlog_entry("(0x%p, '%.*s')\n", dentry, | 901 | mlog_entry("(0x%p, '%.*s')\n", dentry, |
882 | dentry->d_name.len, dentry->d_name.name); | 902 | dentry->d_name.len, dentry->d_name.name); |
@@ -947,11 +967,47 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
947 | } | 967 | } |
948 | } | 968 | } |
949 | 969 | ||
950 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | 970 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || |
951 | if (IS_ERR(handle)) { | 971 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { |
952 | status = PTR_ERR(handle); | 972 | credits = OCFS2_INODE_UPDATE_CREDITS; |
953 | mlog_errno(status); | 973 | if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid |
954 | goto bail_unlock; | 974 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, |
975 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { | ||
976 | oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv; | ||
977 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
978 | if (status < 0) | ||
979 | goto bail_unlock; | ||
980 | credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) + | ||
981 | ocfs2_calc_qdel_credits(sb, USRQUOTA); | ||
982 | locked[USRQUOTA] = 1; | ||
983 | } | ||
984 | if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid | ||
985 | && OCFS2_HAS_RO_COMPAT_FEATURE(sb, | ||
986 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { | ||
987 | oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv; | ||
988 | status = ocfs2_lock_global_qf(oinfo, 1); | ||
989 | if (status < 0) | ||
990 | goto bail_unlock; | ||
991 | credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) + | ||
992 | ocfs2_calc_qdel_credits(sb, GRPQUOTA); | ||
993 | locked[GRPQUOTA] = 1; | ||
994 | } | ||
995 | handle = ocfs2_start_trans(osb, credits); | ||
996 | if (IS_ERR(handle)) { | ||
997 | status = PTR_ERR(handle); | ||
998 | mlog_errno(status); | ||
999 | goto bail_unlock; | ||
1000 | } | ||
1001 | status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; | ||
1002 | if (status < 0) | ||
1003 | goto bail_commit; | ||
1004 | } else { | ||
1005 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
1006 | if (IS_ERR(handle)) { | ||
1007 | status = PTR_ERR(handle); | ||
1008 | mlog_errno(status); | ||
1009 | goto bail_unlock; | ||
1010 | } | ||
955 | } | 1011 | } |
956 | 1012 | ||
957 | /* | 1013 | /* |
@@ -974,6 +1030,12 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
974 | bail_commit: | 1030 | bail_commit: |
975 | ocfs2_commit_trans(osb, handle); | 1031 | ocfs2_commit_trans(osb, handle); |
976 | bail_unlock: | 1032 | bail_unlock: |
1033 | for (qtype = 0; qtype < MAXQUOTAS; qtype++) { | ||
1034 | if (!locked[qtype]) | ||
1035 | continue; | ||
1036 | oinfo = sb_dqinfo(sb, qtype)->dqi_priv; | ||
1037 | ocfs2_unlock_global_qf(oinfo, 1); | ||
1038 | } | ||
977 | ocfs2_inode_unlock(inode, 1); | 1039 | ocfs2_inode_unlock(inode, 1); |
978 | bail_unlock_rw: | 1040 | bail_unlock_rw: |
979 | if (size_change) | 1041 | if (size_change) |