Re: [RFC] quota: 64-bit limits with vfs, updated

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Introduce 64-bit quota limits support with QFMT_VFS_V0. 

This patch is incremental to quota-do-not-allow-setting-of-quota-limits-to-too-high-values.patch included in -mm tree.

Signed-off-by: Andrew Perepechko <andrew.perepechko@xxxxxxx>

---

 fs/quota_v2.c              |  227 ++++++++++++++++++++++++++++++---------------
 include/linux/dqblk_v2.h   |    1
 include/linux/quota.h      |   10 -
 include/linux/quotaio_v2.h |   34 +++++-
 4 files changed, 186 insertions(+), 86 deletions(-)


diff -rNpu linux.2.6.24.3.old/fs/quota_v2.c linux-2.6.24.3/fs/quota_v2.c
--- linux.2.6.24.3.old/fs/quota_v2.c	2008-03-14 15:34:16.000000000 +0300
+++ linux-2.6.24.3/fs/quota_v2.c	2008-03-15 20:52:26.000000000 +0300
@@ -23,26 +23,67 @@ MODULE_LICENSE("GPL");
 typedef char *dqbuf_t;
 
 #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
-#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
+#define GETENTRIES(buf) ((union v2_disk_dqblk *)(((char *)buf) + \
+			 sizeof(struct v2_disk_dqdbheader)))
 
-/* Check whether given file is really vfsv0 quotafile */
-static int v2_check_quota_file(struct super_block *sb, int type)
+static const union v2_disk_dqblk emptydquot;
+static const union v2_disk_dqblk fakedquot[2] = {
+	{.disk_dqblk_r0 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} },
+	{.disk_dqblk_r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} }
+};
+
+static inline uint v2_dqblksz(uint rev)
+{
+	uint sz = 0; /* make the compiler happy */
+
+	switch (rev) {
+	case 0:
+		sz = sizeof(struct v2_disk_dqblk_r0);
+		break;
+	case 1:
+		sz = sizeof(struct v2_disk_dqblk_r1);
+		break;
+	default:
+		BUG();
+	}
+
+	return sz;
+}
+
+/* Number of quota entries in a block */
+static inline int v2_dqstrinblk(uint rev)
+{
+	return (V2_DQBLKSIZE-sizeof(struct v2_disk_dqdbheader))/v2_dqblksz(rev);
+}
+
+/* Get revision of a quota file, -1 if it does not look a quota file */
+static int v2_quota_file_revision(struct super_block *sb, int type)
 {
 	struct v2_disk_dqheader dqhead;
 	ssize_t size;
 	static const uint quota_magics[] = V2_INITQMAGICS;
-	static const uint quota_versions[] = V2_INITQVERSIONS;
+	static const uint quota_versions_r0[] = V2_INITQVERSIONS_R0;
+	static const uint quota_versions_r1[] = V2_INITQVERSIONS_R1;
  
 	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
 	if (size != sizeof(struct v2_disk_dqheader)) {
 		printk("quota_v2: failed read expected=%zd got=%zd\n",
 			sizeof(struct v2_disk_dqheader), size);
-		return 0;
+		return -1;
 	}
-	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
-	    le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
-		return 0;
-	return 1;
+	if (le32_to_cpu(dqhead.dqh_magic) == quota_magics[type]) {
+		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r0[type])
+			return 0;
+		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r1[type])
+			return 1;
+	}
+	return -1;
+}
+
+/* Check whether given file is really vfsv0 quotafile */
+static int v2_check_quota_file(struct super_block *sb, int type)
+{
+	return v2_quota_file_revision(sb, type) != -1;
 }
 
 /* Read information header from quota file */
@@ -51,6 +92,10 @@ static int v2_read_file_info(struct supe
 	struct v2_disk_dqinfo dinfo;
 	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
 	ssize_t size;
+	int rev;
+
+	rev = v2_quota_file_revision(sb, type);
+	BUG_ON(rev < 0);
 
 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
@@ -59,15 +104,22 @@ static int v2_read_file_info(struct supe
 			sb->s_id);
 		return -1;
 	}
-	/* limits are stored as unsigned 32-bit data */
-	info->dqi_maxblimit = 0xffffffff;
-	info->dqi_maxilimit = 0xffffffff;
 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
 	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
 	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
 	info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
 	info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
 	info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+
+	info->u.v2_i.dqi_revision = rev;
+	if (rev == 0) {
+		info->dqi_maxblimit = 0xffffffffULL;
+		info->dqi_maxilimit = 0xffffffffULL;
+	} else {
+		info->dqi_maxblimit = 0xffffffffffffffffULL;
+		info->dqi_maxilimit = 0xffffffffffffffffULL;
+	}
+
 	return 0;
 }
 
@@ -97,29 +149,47 @@ static int v2_write_file_info(struct sup
 	return 0;
 }
 
-static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
-{
-	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
-	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
-	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
-	m->dqb_itime = le64_to_cpu(d->dqb_itime);
-	m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
-	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
-	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
-	m->dqb_btime = le64_to_cpu(d->dqb_btime);
-}
-
-static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
-{
-	d->dqb_ihardlimit = cpu_to_le32((u32)m->dqb_ihardlimit);
-	d->dqb_isoftlimit = cpu_to_le32((u32)m->dqb_isoftlimit);
-	d->dqb_curinodes = cpu_to_le32((u32)m->dqb_curinodes);
-	d->dqb_itime = cpu_to_le64(m->dqb_itime);
-	d->dqb_bhardlimit = cpu_to_le32((u32)m->dqb_bhardlimit);
-	d->dqb_bsoftlimit = cpu_to_le32((u32)m->dqb_bsoftlimit);
-	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
-	d->dqb_btime = cpu_to_le64(m->dqb_btime);
-	d->dqb_id = cpu_to_le32(id);
+#define DQ2MQ(v) (sizeof(v) == sizeof(__u64) ? \
+		  (qsize_t)le64_to_cpu(v) : \
+		  (qsize_t)le32_to_cpu(v))
+
+#define MQ2DQ(v, newv) (sizeof(v) == sizeof(__u64) ? \
+			(v = cpu_to_le64((__u64)newv)) : \
+			(v = cpu_to_le32((__u32)newv)))
+
+#define DQF_GET(var, rev, field) (rev == 0 ? \
+		DQ2MQ((var)->disk_dqblk_r0.field) : \
+		DQ2MQ((var)->disk_dqblk_r1.field))
+
+#define DQF_PUT(var, rev, field, val) (rev == 0 ? \
+		MQ2DQ((var)->disk_dqblk_r0.field, val) : \
+		MQ2DQ((var)->disk_dqblk_r1.field, val))
+
+void disk2memdqb(struct mem_dqblk *m, union v2_disk_dqblk *d,
+		 uint rev)
+{
+	m->dqb_ihardlimit = DQF_GET(d, rev, dqb_ihardlimit);
+	m->dqb_isoftlimit = DQF_GET(d, rev, dqb_isoftlimit);
+	m->dqb_curinodes = DQF_GET(d, rev, dqb_curinodes);
+	m->dqb_itime = DQF_GET(d, rev, dqb_itime);
+	m->dqb_bhardlimit = DQF_GET(d, rev, dqb_bhardlimit);
+	m->dqb_bsoftlimit = DQF_GET(d, rev, dqb_bsoftlimit);
+	m->dqb_curspace = DQF_GET(d, rev, dqb_curspace);
+	m->dqb_btime = DQF_GET(d, rev, dqb_btime);
+}
+
+static void mem2diskdqb(union v2_disk_dqblk *d, struct mem_dqblk *m,
+			qid_t id, uint rev)
+{
+	DQF_PUT(d, rev, dqb_ihardlimit, m->dqb_ihardlimit);
+	DQF_PUT(d, rev, dqb_isoftlimit, m->dqb_isoftlimit);
+	DQF_PUT(d, rev, dqb_curinodes, m->dqb_curinodes);
+	DQF_PUT(d, rev, dqb_itime, m->dqb_itime);
+	DQF_PUT(d, rev, dqb_bhardlimit, m->dqb_bhardlimit);
+	DQF_PUT(d, rev, dqb_bsoftlimit, m->dqb_bsoftlimit);
+	DQF_PUT(d, rev, dqb_curspace, m->dqb_curspace);
+	DQF_PUT(d, rev, dqb_btime, m->dqb_btime);
+	DQF_PUT(d, rev, dqb_id, id);
 }
 
 static dqbuf_t getdqbuf(void)
@@ -271,10 +341,10 @@ static uint find_free_dqentry(struct dqu
 {
 	struct super_block *sb = dquot->dq_sb;
 	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
-	uint blk, i;
+	uint blk, i, rev = info->u.v2_i.dqi_revision;
+	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
 	struct v2_disk_dqdbheader *dh;
-	struct v2_disk_dqblk *ddquot;
-	struct v2_disk_dqblk fakedquot;
+	union v2_disk_dqblk *ddquot;
 	dqbuf_t buf;
 
 	*err = 0;
@@ -301,17 +371,18 @@ static uint find_free_dqentry(struct dqu
 		info->u.v2_i.dqi_free_entry = blk;
 		mark_info_dirty(sb, dquot->dq_type);
 	}
-	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
+	/* Block will be full? */
+	if (le16_to_cpu(dh->dqdh_entries)+1 >= dqstrinblk)
 		if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
 			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
 			goto out_buf;
 		}
 	dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
-	memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
 	/* Find free structure in block */
-	for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
+	for (i = 0; i < dqstrinblk && memcmp(&emptydquot,
+			ddquot+i, dqblksz); i++);
 #ifdef __QUOTA_V2_PARANOIA
-	if (i == V2_DQSTRINBLK) {
+	if (i == dqstrinblk) {
 		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
 		*err = -EIO;
 		goto out_buf;
@@ -321,7 +392,8 @@ static uint find_free_dqentry(struct dqu
 		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
 		goto out_buf;
 	}
-	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
+	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+
+			sizeof(struct v2_disk_dqdbheader)+i*dqblksz;
 	freedqbuf(buf);
 	return blk;
 out_buf:
@@ -395,7 +467,9 @@ static int v2_write_dquot(struct dquot *
 {
 	int type = dquot->dq_type;
 	ssize_t ret;
-	struct v2_disk_dqblk ddquot, empty;
+	union v2_disk_dqblk ddquot;
+	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
+	uint dqblksz = v2_dqblksz(rev);
 
 	/* dq_off is guarded by dqio_mutex */
 	if (!dquot->dq_off)
@@ -404,18 +478,18 @@ static int v2_write_dquot(struct dquot *
 			return ret;
 		}
 	spin_lock(&dq_data_lock);
-	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
+	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, rev);
 	/* Argh... We may need to write structure full of zeroes but that would be
 	 * treated as an empty place by the rest of the code. Format change would
 	 * be definitely cleaner but the problems probably are not worth it */
-	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-		ddquot.dqb_itime = cpu_to_le64(1);
+	if (!memcmp(&emptydquot, &ddquot, dqblksz))
+		DQF_PUT(&ddquot, rev, dqb_itime, 1);
 	spin_unlock(&dq_data_lock);
 	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
-	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
-	if (ret != sizeof(struct v2_disk_dqblk)) {
-		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
+	      (char *)&ddquot, dqblksz, dquot->dq_off);
+	if (ret != dqblksz) {
+		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
+			dquot->dq_sb->s_id);
 		if (ret >= 0)
 			ret = -ENOSPC;
 	}
@@ -434,6 +508,7 @@ static int free_dqentry(struct dquot *dq
 	struct v2_disk_dqdbheader *dh;
 	dqbuf_t buf = getdqbuf();
 	int ret = 0;
+	uint rev = sb_dqopt(sb)->info[type].u.v2_i.dqi_revision;
 
 	if (!buf)
 		return -ENOMEM;
@@ -459,8 +534,8 @@ static int free_dqentry(struct dquot *dq
 	}
 	else {
 		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
-		  sizeof(struct v2_disk_dqblk));
-		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
+		  v2_dqblksz(rev));
+		if (le16_to_cpu(dh->dqdh_entries) == v2_dqstrinblk(rev)-1) {
 			/* Insert will write block itself */
 			if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
 				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
@@ -538,27 +613,29 @@ static loff_t find_block_dqentry(struct
 	dqbuf_t buf = getdqbuf();
 	loff_t ret = 0;
 	int i;
-	struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
+	union v2_disk_dqblk *ddquot = GETENTRIES(buf);
+	int type = dquot->dq_type;
+	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
+	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
 
 	if (!buf)
 		return -ENOMEM;
-	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
+
+	ret = read_blk(dquot->dq_sb, type, blk, buf);
+	if (ret < 0) {
 		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
 		goto out_buf;
 	}
 	if (dquot->dq_id)
-		for (i = 0; i < V2_DQSTRINBLK &&
-		     le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
+		for (i = 0; i < dqstrinblk &&
+		     DQF_GET(ddquot+i, rev, dqb_id) != dquot->dq_id; i++);
 	else {	/* ID 0 as a bit more complicated searching... */
-		struct v2_disk_dqblk fakedquot;
-
-		memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
-		for (i = 0; i < V2_DQSTRINBLK; i++)
-			if (!le32_to_cpu(ddquot[i].dqb_id) &&
-			    memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
+		for (i = 0; i < dqstrinblk; i++)
+			if (!DQF_GET(ddquot+i, rev, dqb_id) &&
+			    memcmp(&emptydquot, ddquot+i, dqblksz))
 				break;
 	}
-	if (i == V2_DQSTRINBLK) {
+	if (i == dqstrinblk) {
 		printk(KERN_ERR "VFS: Quota for id %u referenced "
 		  "but not present.\n", dquot->dq_id);
 		ret = -EIO;
@@ -566,7 +643,7 @@ static loff_t find_block_dqentry(struct
 	}
 	else
 		ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
-		  v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
+		  v2_disk_dqdbheader) + i * dqblksz;
 out_buf:
 	freedqbuf(buf);
 	return ret;
@@ -608,7 +685,7 @@ static int v2_read_dquot(struct dquot *d
 {
 	int type = dquot->dq_type;
 	loff_t offset;
-	struct v2_disk_dqblk ddquot, empty;
+	union v2_disk_dqblk ddquot;
 	int ret = 0;
 
 #ifdef __QUOTA_V2_PARANOIA
@@ -629,25 +706,25 @@ static int v2_read_dquot(struct dquot *d
 		ret = offset;
 	}
 	else {
+		uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.
+			   dqi_revision, dqblksz = v2_dqblksz(rev);
 		dquot->dq_off = offset;
-		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
-		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
-		    != sizeof(struct v2_disk_dqblk)) {
+		ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
+					   (char *)&ddquot, dqblksz, offset);
+		if (ret != dqblksz) {
 			if (ret >= 0)
 				ret = -EIO;
 			printk(KERN_ERR "VFS: Error while reading quota "
 			  "structure for id %u.\n", dquot->dq_id);
-			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
+			memset(&ddquot, 0, dqblksz);
 		}
 		else {
 			ret = 0;
 			/* We need to escape back all-zero structure */
-			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-			empty.dqb_itime = cpu_to_le64(1);
-			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-				ddquot.dqb_itime = 0;
+			if (!memcmp(&fakedquot[rev], &ddquot, dqblksz))
+				DQF_PUT(&ddquot, rev, dqb_itime, 0);
 		}
-		disk2memdqb(&dquot->dq_dqb, &ddquot);
+		disk2memdqb(&dquot->dq_dqb, &ddquot, rev);
 		if (!dquot->dq_dqb.dqb_bhardlimit &&
 			!dquot->dq_dqb.dqb_bsoftlimit &&
 			!dquot->dq_dqb.dqb_ihardlimit &&
diff -rNpu linux.2.6.24.3.old/include/linux/dqblk_v2.h linux-2.6.24.3/include/linux/dqblk_v2.h
--- linux.2.6.24.3.old/include/linux/dqblk_v2.h	2008-02-26 03:20:20.000000000 +0300
+++ linux-2.6.24.3/include/linux/dqblk_v2.h	2008-03-13 22:01:48.000000000 +0300
@@ -21,6 +21,7 @@ struct v2_mem_dqinfo {
 	unsigned int dqi_blocks;
 	unsigned int dqi_free_blk;
 	unsigned int dqi_free_entry;
+	unsigned int dqi_revision;
 };
 
 #endif /* _LINUX_DQBLK_V2_H */
diff -rNpu linux.2.6.24.3.old/include/linux/quota.h linux-2.6.24.3/include/linux/quota.h
--- linux.2.6.24.3.old/include/linux/quota.h	2008-03-14 15:34:16.000000000 +0300
+++ linux-2.6.24.3/include/linux/quota.h	2008-03-13 22:01:48.000000000 +0300
@@ -181,12 +181,12 @@ extern spinlock_t dq_data_lock;
  * Data for one user/group kept in memory
  */
 struct mem_dqblk {
-	__u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
-	__u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
+	qsize_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
+	qsize_t dqb_bsoftlimit;	/* preferred limit on disk blks */
 	qsize_t dqb_curspace;	/* current used space */
-	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
-	__u32 dqb_isoftlimit;	/* preferred inode limit */
-	__u32 dqb_curinodes;	/* current # allocated inodes */
+	qsize_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	qsize_t dqb_isoftlimit;	/* preferred inode limit */
+	qsize_t dqb_curinodes;	/* current # allocated inodes */
 	time_t dqb_btime;	/* time limit for excessive disk use */
 	time_t dqb_itime;	/* time limit for excessive inode use */
 };
diff -rNpu linux.2.6.24.3.old/include/linux/quotaio_v2.h linux-2.6.24.3/include/linux/quotaio_v2.h
--- linux.2.6.24.3.old/include/linux/quotaio_v2.h	2008-02-26 03:20:20.000000000 +0300
+++ linux-2.6.24.3/include/linux/quotaio_v2.h	2008-03-13 22:01:48.000000000 +0300
@@ -16,28 +16,51 @@
 	0xd9c01927	/* GRPQUOTA */\
 }
 
-#define V2_INITQVERSIONS {\
+#define V2_INITQVERSIONS_R0 {\
 	0,		/* USRQUOTA */\
 	0		/* GRPQUOTA */\
 }
 
+#define V2_INITQVERSIONS_R1 {\
+	1,		/* USRQUOTA */\
+	1		/* GRPQUOTA */\
+}
+
 /*
  * The following structure defines the format of the disk quota file
  * (as it appears on disk) - the file is a radix tree whose leaves point
  * to blocks of these structures.
  */
-struct v2_disk_dqblk {
+struct v2_disk_dqblk_r0 {
 	__le32 dqb_id;		/* id this quota applies to */
 	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
 	__le32 dqb_isoftlimit;	/* preferred inode limit */
 	__le32 dqb_curinodes;	/* current # allocated inodes */
-	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
-	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+	__le32 dqb_bhardlimit;	/* absolute limit on disk space */
+	__le32 dqb_bsoftlimit;	/* preferred limit on disk space */
+	__le64 dqb_curspace;	/* current space occupied (in bytes) */
+	__le64 dqb_btime;	/* time limit for excessive disk use */
+	__le64 dqb_itime;	/* time limit for excessive inode use */
+};
+
+struct v2_disk_dqblk_r1 {
+	__le32 dqb_id;		/* id this quota applies to */
+	__le32 dqb_padding;	/* padding field */
+	__le64 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	__le64 dqb_isoftlimit;	/* preferred inode limit */
+	__le64 dqb_curinodes;	/* current # allocated inodes */
+	__le64 dqb_bhardlimit;	/* absolute limit on disk space */
+	__le64 dqb_bsoftlimit;	/* preferred limit on disk space */
 	__le64 dqb_curspace;	/* current space occupied (in bytes) */
 	__le64 dqb_btime;	/* time limit for excessive disk use */
 	__le64 dqb_itime;	/* time limit for excessive inode use */
 };
 
+union v2_disk_dqblk {
+	struct v2_disk_dqblk_r0 disk_dqblk_r0;
+	struct v2_disk_dqblk_r1 disk_dqblk_r1;
+};
+
 /*
  * Here are header structures as written on disk and their in-memory copies
  */
@@ -59,7 +82,7 @@ struct v2_disk_dqinfo {
 
 /*
  *  Structure of header of block with quota structures. It is padded to 16 bytes so
- *  there will be space for exactly 21 quota-entries in a block
+ *  there will be space for exactly 21 (r0) or 14 (r1) quota-entries in a block
  */
 struct v2_disk_dqdbheader {
 	__le32 dqdh_next_free;	/* Number of next block with free entry */
@@ -74,6 +97,5 @@ struct v2_disk_dqdbheader {
 #define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
 #define V2_DQTREEOFF	1		/* Offset of tree in file in blocks */
 #define V2_DQTREEDEPTH	4		/* Depth of quota tree */
-#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
 
 #endif /* _LINUX_QUOTAIO_V2_H */
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux