summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-01-06 21:15:46 +0100
committerJan Kara <jack@suse.cz>2011-01-06 21:15:46 +0100
commit8a4dc3612c6c170c05e5eef68dd3555baeb341c1 (patch)
tree3df70c155be8776c1f549cdbe7e8a677453e8efc
parent346d2f876c988747f9dc1c57aa8c6fc92052e5de (diff)
Check whether set limits fit into the range supported by quota format.
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--Changelog2
-rw-r--r--quotaio.c24
-rw-r--r--quotaio.h8
-rw-r--r--quotaio_v1.c8
-rw-r--r--quotaio_v2.c23
5 files changed, 64 insertions, 1 deletions
diff --git a/Changelog b/Changelog
index 416cd2c..fb52bbe 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,6 @@
Changes in quota-tools from 3.17 to 4.00-pre2
+* check whether set limits fit into range supported by quota format (Jan Kara)
+* remove checking of filesystem type from hasquota() (Jan Kara)
* create quota-nfs.sh script for nicer quota(1) output formatting on some NFS clients (Jan Kara)
* add options for quota(1) modifying formatting of filesystem identificaion (Jan Kara)
* minor updates of manpages (Jan Kara)
diff --git a/quotaio.c b/quotaio.c
index dbd7cc8..21881fc 100644
--- a/quotaio.c
+++ b/quotaio.c
@@ -287,3 +287,27 @@ struct dquot *get_empty_dquot(void)
dquot->dq_id = -1;
return dquot;
}
+
+/*
+ * Check whether values in current dquot can be stored on disk
+ */
+int check_dquot_range(struct dquot *dquot)
+{
+ struct util_dqinfo *info = &dquot->dq_h->qh_info;
+
+ if (dquot->dq_dqb.dqb_bhardlimit > info->dqi_max_b_limit ||
+ dquot->dq_dqb.dqb_bsoftlimit > info->dqi_max_b_limit ||
+ dquot->dq_dqb.dqb_ihardlimit > info->dqi_max_i_limit ||
+ dquot->dq_dqb.dqb_isoftlimit > info->dqi_max_i_limit) {
+ errstr(_("Trying to set quota limits out of range "
+ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
+ return -1;
+ }
+ if (dquot->dq_dqb.dqb_curinodes > info->dqi_max_i_usage ||
+ dquot->dq_dqb.dqb_curspace > info->dqi_max_b_usage) {
+ errstr(_("Trying to set quota usage out of range "
+ "supported by quota format on %s.\n"), dquot->dq_h->qh_quotadev);
+ return -1;
+ }
+ return 0;
+}
diff --git a/quotaio.h b/quotaio.h
index d797034..3cd33ba 100644
--- a/quotaio.h
+++ b/quotaio.h
@@ -10,6 +10,7 @@
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdint.h>
#include "quota.h"
#include "mntopt.h"
@@ -69,6 +70,10 @@ struct quotafile_ops;
struct util_dqinfo {
time_t dqi_bgrace; /* Block grace time for given quotafile */
time_t dqi_igrace; /* Inode grace time for given quotafile */
+ uint64_t dqi_max_b_limit; /* Maximal block limit storable in current format */
+ uint64_t dqi_max_i_limit; /* Maximal inode limit storable in current format */
+ uint64_t dqi_max_b_usage; /* Maximal block usage storable in current format */
+ uint64_t dqi_max_i_usage; /* Maximal inode usage storable in current format */
union {
struct v2_mem_dqinfo v2_mdqi;
struct xfs_mem_dqinfo xfs_mdqi;
@@ -171,4 +176,7 @@ int end_io(struct quota_handle *h);
/* Get empty quota structure */
struct dquot *get_empty_dquot(void);
+/* Check whether values in current dquot can be stored on disk */
+int check_dquot_range(struct dquot *dquot);
+
#endif /* GUARD_QUOTAIO_H */
diff --git a/quotaio_v1.c b/quotaio_v1.c
index 1533ffc..305bff2 100644
--- a/quotaio_v1.c
+++ b/quotaio_v1.c
@@ -174,6 +174,10 @@ static int v1_init_io(struct quota_handle *h)
h->qh_info.dqi_bgrace = MAX_DQ_TIME;
if (!h->qh_info.dqi_igrace)
h->qh_info.dqi_igrace = MAX_IQ_TIME;
+ h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_b_usage = ((uint64_t)(~(uint32_t)0)) << V1_DQBLK_SIZE_BITS;
+ h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
return 0;
}
@@ -327,6 +331,10 @@ static int v1_commit_dquot(struct dquot *dquot, int flags)
}
}
else {
+ if (check_dquot_range(dquot) < 0) {
+ errno = ERANGE;
+ return -1;
+ }
v1_mem2diskdqblk(&ddqblk, &dquot->dq_dqb);
lseek(h->qh_fd, (long)V1_DQOFF(dquot->dq_id), SEEK_SET);
if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
diff --git a/quotaio_v2.c b/quotaio_v2.c
index 38440e7..2242c88 100644
--- a/quotaio_v2.c
+++ b/quotaio_v2.c
@@ -307,9 +307,17 @@ static int v2_init_io(struct quota_handle *h)
if (__le32_to_cpu(header.dqh_version) == 0) {
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops;
+ h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
} else {
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
+ h->qh_info.dqi_max_b_limit = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_limit = ~(uint64_t)0;
+ h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_usage = ~(uint64_t)0;
}
} else {
/* We don't have the file open -> we don't need quota tree operations */
@@ -351,9 +359,17 @@ static int v2_new_io(struct quota_handle *h)
if (version == 0) {
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops;
+ h->qh_info.dqi_max_b_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_i_limit = ~(uint32_t)0;
+ h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_usage = ~(uint32_t)0;
} else if (version == 1) {
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops;
+ h->qh_info.dqi_max_b_limit = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_limit = ~(uint64_t)0;
+ h->qh_info.dqi_max_b_usage = ~(uint64_t)0;
+ h->qh_info.dqi_max_i_usage = ~(uint64_t)0;
}
v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET);
@@ -477,8 +493,13 @@ static int v2_commit_dquot(struct dquot *dquot, int flags)
if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && !b->dqb_isoftlimit
&& !b->dqb_bhardlimit && !b->dqb_ihardlimit)
qtree_delete_dquot(dquot);
- else
+ else {
+ if (check_dquot_range(dquot) < 0) {
+ errno = ERANGE;
+ return -1;
+ }
qtree_write_dquot(dquot);
+ }
return 0;
}