aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhi Das <adas@redhat.com>2015-03-18 13:04:37 -0400
committerBob Peterson <rpeterso@redhat.com>2015-03-18 13:47:10 -0400
commit25435e5ed611f310dda889940cbc4c45b3ecd9ec (patch)
tree9610acd909a2a48a01f092a58c163af4cac1aad2
parentb8fbf471edb3dbf441716fd2a52a7ca76c381381 (diff)
gfs2: allow quota_check and inplace_reserve to return available blocks
struct gfs2_alloc_parms is passed to gfs2_quota_check() and gfs2_inplace_reserve() with ap->target containing the number of blocks being requested for allocation in the current operation. We add a new field to struct gfs2_alloc_parms called 'allowed'. gfs2_quota_check() and gfs2_inplace_reserve() return the max blocks allowed by quota and the max blocks allowed by the chosen rgrp respectively in 'allowed'. A new field 'min_target', when non-zero, tells gfs2_quota_check() and gfs2_inplace_reserve() to not return -EDQUOT/-ENOSPC when there are atleast 'min_target' blocks allowable/available. The assumption is that the caller is ok with just 'min_target' blocks and will likely proceed with allocating them. Signed-off-by: Abhi Das <adas@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com> Acked-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/incore.h2
-rw-r--r--fs/gfs2/quota.c52
-rw-r--r--fs/gfs2/rgrp.c20
-rw-r--r--fs/gfs2/rgrp.h3
4 files changed, 58 insertions, 19 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 3a4ea50c9113..58b75abf6ab2 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -302,7 +302,9 @@ struct gfs2_blkreserv {
302 */ 302 */
303struct gfs2_alloc_parms { 303struct gfs2_alloc_parms {
304 u64 target; 304 u64 target;
305 u32 min_target;
305 u32 aflags; 306 u32 aflags;
307 u64 allowed;
306}; 308};
307 309
308enum { 310enum {
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 964a769a7a86..55614685a31c 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1094,15 +1094,33 @@ static int print_message(struct gfs2_quota_data *qd, char *type)
1094 return 0; 1094 return 0;
1095} 1095}
1096 1096
1097/**
1098 * gfs2_quota_check - check if allocating new blocks will exceed quota
1099 * @ip: The inode for which this check is being performed
1100 * @uid: The uid to check against
1101 * @gid: The gid to check against
1102 * @ap: The allocation parameters. ap->target contains the requested
1103 * blocks. ap->min_target, if set, contains the minimum blks
1104 * requested.
1105 *
1106 * Returns: 0 on success.
1107 * min_req = ap->min_target ? ap->min_target : ap->target;
1108 * quota must allow atleast min_req blks for success and
1109 * ap->allowed is set to the number of blocks allowed
1110 *
1111 * -EDQUOT otherwise, quota violation. ap->allowed is set to number
1112 * of blocks available.
1113 */
1097int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid, 1114int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
1098 struct gfs2_alloc_parms *ap) 1115 struct gfs2_alloc_parms *ap)
1099{ 1116{
1100 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1117 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1101 struct gfs2_quota_data *qd; 1118 struct gfs2_quota_data *qd;
1102 s64 value; 1119 s64 value, warn, limit;
1103 unsigned int x; 1120 unsigned int x;
1104 int error = 0; 1121 int error = 0;
1105 1122
1123 ap->allowed = UINT_MAX; /* Assume we are permitted a whole lot */
1106 if (!test_bit(GIF_QD_LOCKED, &ip->i_flags)) 1124 if (!test_bit(GIF_QD_LOCKED, &ip->i_flags))
1107 return 0; 1125 return 0;
1108 1126
@@ -1116,29 +1134,37 @@ int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid,
1116 qid_eq(qd->qd_id, make_kqid_gid(gid)))) 1134 qid_eq(qd->qd_id, make_kqid_gid(gid))))
1117 continue; 1135 continue;
1118 1136
1137 warn = (s64)be64_to_cpu(qd->qd_qb.qb_warn);
1138 limit = (s64)be64_to_cpu(qd->qd_qb.qb_limit);
1119 value = (s64)be64_to_cpu(qd->qd_qb.qb_value); 1139 value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
1120 spin_lock(&qd_lock); 1140 spin_lock(&qd_lock);
1121 value += qd->qd_change + ap->target; 1141 value += qd->qd_change;
1122 spin_unlock(&qd_lock); 1142 spin_unlock(&qd_lock);
1123 1143
1124 if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) { 1144 if (limit > 0 && (limit - value) < ap->allowed)
1125 print_message(qd, "exceeded"); 1145 ap->allowed = limit - value;
1126 quota_send_warning(qd->qd_id, 1146 /* If we can't meet the target */
1127 sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN); 1147 if (limit && limit < (value + (s64)ap->target)) {
1128 error = -EDQUOT; 1148 /* If no min_target specified or we don't meet
1129 break; 1149 * min_target, return -EDQUOT */
1130 } else if (be64_to_cpu(qd->qd_qb.qb_warn) && 1150 if (!ap->min_target || ap->min_target > ap->allowed) {
1131 (s64)be64_to_cpu(qd->qd_qb.qb_warn) < value && 1151 print_message(qd, "exceeded");
1152 quota_send_warning(qd->qd_id,
1153 sdp->sd_vfs->s_dev,
1154 QUOTA_NL_BHARDWARN);
1155 error = -EDQUOT;
1156 break;
1157 }
1158 } else if (warn && warn < value &&
1132 time_after_eq(jiffies, qd->qd_last_warn + 1159 time_after_eq(jiffies, qd->qd_last_warn +
1133 gfs2_tune_get(sdp, 1160 gfs2_tune_get(sdp, gt_quota_warn_period)
1134 gt_quota_warn_period) * HZ)) { 1161 * HZ)) {
1135 quota_send_warning(qd->qd_id, 1162 quota_send_warning(qd->qd_id,
1136 sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN); 1163 sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);
1137 error = print_message(qd, "warning"); 1164 error = print_message(qd, "warning");
1138 qd->qd_last_warn = jiffies; 1165 qd->qd_last_warn = jiffies;
1139 } 1166 }
1140 } 1167 }
1141
1142 return error; 1168 return error;
1143} 1169}
1144 1170
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 9150207f365c..6af2396a317c 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1946,10 +1946,18 @@ static inline int fast_to_acquire(struct gfs2_rgrpd *rgd)
1946 * @ip: the inode to reserve space for 1946 * @ip: the inode to reserve space for
1947 * @ap: the allocation parameters 1947 * @ap: the allocation parameters
1948 * 1948 *
1949 * Returns: errno 1949 * We try our best to find an rgrp that has at least ap->target blocks
1950 * available. After a couple of passes (loops == 2), the prospects of finding
1951 * such an rgrp diminish. At this stage, we return the first rgrp that has
1952 * atleast ap->min_target blocks available. Either way, we set ap->allowed to
1953 * the number of blocks available in the chosen rgrp.
1954 *
1955 * Returns: 0 on success,
1956 * -ENOMEM if a suitable rgrp can't be found
1957 * errno otherwise
1950 */ 1958 */
1951 1959
1952int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap) 1960int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
1953{ 1961{
1954 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1962 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1955 struct gfs2_rgrpd *begin = NULL; 1963 struct gfs2_rgrpd *begin = NULL;
@@ -2012,7 +2020,7 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
2012 /* Skip unuseable resource groups */ 2020 /* Skip unuseable resource groups */
2013 if ((rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | 2021 if ((rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC |
2014 GFS2_RDF_ERROR)) || 2022 GFS2_RDF_ERROR)) ||
2015 (ap->target > rs->rs_rbm.rgd->rd_extfail_pt)) 2023 (loops == 0 && ap->target > rs->rs_rbm.rgd->rd_extfail_pt))
2016 goto skip_rgrp; 2024 goto skip_rgrp;
2017 2025
2018 if (sdp->sd_args.ar_rgrplvb) 2026 if (sdp->sd_args.ar_rgrplvb)
@@ -2027,11 +2035,13 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
2027 goto check_rgrp; 2035 goto check_rgrp;
2028 2036
2029 /* If rgrp has enough free space, use it */ 2037 /* If rgrp has enough free space, use it */
2030 if (rs->rs_rbm.rgd->rd_free_clone >= ap->target) { 2038 if (rs->rs_rbm.rgd->rd_free_clone >= ap->target ||
2039 (loops == 2 && ap->min_target &&
2040 rs->rs_rbm.rgd->rd_free_clone >= ap->min_target)) {
2031 ip->i_rgd = rs->rs_rbm.rgd; 2041 ip->i_rgd = rs->rs_rbm.rgd;
2042 ap->allowed = ip->i_rgd->rd_free_clone;
2032 return 0; 2043 return 0;
2033 } 2044 }
2034
2035check_rgrp: 2045check_rgrp:
2036 /* Check for unlinked inodes which can be reclaimed */ 2046 /* Check for unlinked inodes which can be reclaimed */
2037 if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK) 2047 if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK)
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b104f4af3afd..68972ecfbb01 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -41,7 +41,8 @@ extern void gfs2_rgrp_go_unlock(struct gfs2_holder *gh);
41extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip); 41extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
42 42
43#define GFS2_AF_ORLOV 1 43#define GFS2_AF_ORLOV 1
44extern int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap); 44extern int gfs2_inplace_reserve(struct gfs2_inode *ip,
45 struct gfs2_alloc_parms *ap);
45extern void gfs2_inplace_release(struct gfs2_inode *ip); 46extern void gfs2_inplace_release(struct gfs2_inode *ip);
46 47
47extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n, 48extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,