From: Jan Kara <jack@suse.cz>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-fsdevel@vger.kernel.org, Jan Kara <jack@suse.cz>,
Andrew Perepechko <andrew.perepechko@sun.com>
Subject: [PATCH 14/14] quota: Support 64-bit quota format
Date: Mon, 27 Oct 2008 13:11:52 +0100 [thread overview]
Message-ID: <1225109513200-git-send-email-jack@suse.cz> (raw)
In-Reply-To: <122510951372-git-send-email-jack@suse.cz>
Implement conversion functions for new version (version 1) of quota
format which supports 64-bit block and inode limits and 64-bit inode
usage. The original implementation has been written by Andrew Perepechko.
Signed-off-by: Andrew Perepechko <andrew.perepechko@sun.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/quota_v2.c | 140 ++++++++++++++++++++++++++++++++++++++++++++-----------
fs/quotaio_v2.h | 26 ++++++++--
2 files changed, 132 insertions(+), 34 deletions(-)
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index a371919..ac6668d 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -23,14 +23,24 @@ MODULE_LICENSE("GPL");
#define __QUOTA_V2_PARANOIA
-static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
-static void v2_disk2memdqb(struct dquot *dquot, void *dp);
-static int v2_is_id(void *dp, struct dquot *dquot);
-
-static struct qtree_fmt_operations v2_qtree_ops = {
- .mem2disk_dqblk = v2_mem2diskdqb,
- .disk2mem_dqblk = v2_disk2memdqb,
- .is_id = v2_is_id,
+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
+static int v2r0_is_id(void *dp, struct dquot *dquot);
+
+static struct qtree_fmt_operations v2r0_qtree_ops = {
+ .mem2disk_dqblk = v2r0_mem2diskdqb,
+ .disk2mem_dqblk = v2r0_disk2memdqb,
+ .is_id = v2r0_is_id,
+};
+
+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
+static int v2r1_is_id(void *dp, struct dquot *dquot);
+
+static struct qtree_fmt_operations v2r1_qtree_ops = {
+ .mem2disk_dqblk = v2r1_mem2diskdqb,
+ .disk2mem_dqblk = v2r1_disk2memdqb,
+ .is_id = v2r1_is_id,
};
#define QUOTABLOCK_BITS 10
@@ -46,8 +56,7 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
return blocks << QUOTABLOCK_BITS;
}
-/* Check whether given file is really vfsv0 quotafile */
-static int v2_check_quota_file(struct super_block *sb, int type)
+static int v2_check_quota_file_header(struct super_block *sb, int type)
{
struct v2_disk_dqheader dqhead;
ssize_t size;
@@ -58,12 +67,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
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 -EIO;
}
- 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])
+ return -ENOENT;
+ if (le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
+ return -EOPNOTSUPP;
+ return le32_to_cpu(dqhead.dqh_version);
+}
+
+
+/* Check whether given file is really vfsv0 quotafile */
+static int v2_check_quota_file(struct super_block *sb, int type)
+{
+ return v2_check_quota_file_header(sb, type) >= 0;
}
/* Read information header from quota file */
@@ -73,7 +90,13 @@ static int v2_read_file_info(struct super_block *sb, int type)
struct mem_dqinfo *info = sb_dqinfo(sb, type);
struct qtree_mem_dqinfo *qinfo;
ssize_t size;
+ int version = v2_check_quota_file_header(sb, type);
+ if (version < 0) {
+ printk(KERN_WARNING "Cannot identify quota file version on "
+ "device %s: %d\n", sb->s_id, version);
+ return -1;
+ }
size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
if (size != sizeof(struct v2_disk_dqinfo)) {
@@ -88,9 +111,14 @@ static int v2_read_file_info(struct super_block *sb, int type)
return -1;
}
qinfo = info->dqi_priv;
- /* limits are stored as unsigned 32-bit data */
- info->dqi_maxblimit = 0xffffffff;
- info->dqi_maxilimit = 0xffffffff;
+ if (version == 0) {
+ /* limits are stored as unsigned 32-bit data */
+ info->dqi_maxblimit = 0xffffffff;
+ info->dqi_maxilimit = 0xffffffff;
+ } else {
+ info->dqi_maxblimit = 0x7fffffffffffffff;
+ info->dqi_maxilimit = 0x7fffffffffffffff;
+ }
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);
@@ -102,8 +130,13 @@ static int v2_read_file_info(struct super_block *sb, int type)
qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
qinfo->dqi_qtree_depth = qtree_depth(qinfo);
- qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk);
- qinfo->dqi_ops = &v2_qtree_ops;
+ if (version == 0) {
+ qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
+ qinfo->dqi_ops = &v2r0_qtree_ops;
+ } else {
+ qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
+ qinfo->dqi_ops = &v2r1_qtree_ops;
+ }
return 0;
}
@@ -134,9 +167,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
return 0;
}
-static void v2_disk2memdqb(struct dquot *dquot, void *dp)
+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
{
- struct v2_disk_dqblk *d = dp, empty;
+ struct v2r0_disk_dqblk *d = dp, empty;
struct mem_dqblk *m = &dquot->dq_dqb;
m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
@@ -148,15 +181,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
m->dqb_btime = le64_to_cpu(d->dqb_btime);
/* We need to escape back all-zero structure */
- memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+ memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
empty.dqb_itime = cpu_to_le64(1);
- if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
+ if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
m->dqb_itime = 0;
}
-static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
{
- struct v2_disk_dqblk *d = dp;
+ struct v2r0_disk_dqblk *d = dp;
struct mem_dqblk *m = &dquot->dq_dqb;
struct qtree_mem_dqinfo *info =
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
@@ -174,9 +207,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
d->dqb_itime = cpu_to_le64(1);
}
-static int v2_is_id(void *dp, struct dquot *dquot)
+static int v2r0_is_id(void *dp, struct dquot *dquot)
+{
+ struct v2r0_disk_dqblk *d = dp;
+ struct qtree_mem_dqinfo *info =
+ sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+ if (qtree_entry_unused(info, dp))
+ return 0;
+ return le32_to_cpu(d->dqb_id) == dquot->dq_id;
+}
+
+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
+{
+ struct v2r1_disk_dqblk *d = dp, empty;
+ struct mem_dqblk *m = &dquot->dq_dqb;
+
+ m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
+ m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
+ m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
+ m->dqb_itime = le64_to_cpu(d->dqb_itime);
+ m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
+ m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
+ m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
+ m->dqb_btime = le64_to_cpu(d->dqb_btime);
+ /* We need to escape back all-zero structure */
+ memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
+ empty.dqb_itime = cpu_to_le64(1);
+ if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
+ m->dqb_itime = 0;
+}
+
+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
+{
+ struct v2r1_disk_dqblk *d = dp;
+ struct mem_dqblk *m = &dquot->dq_dqb;
+ struct qtree_mem_dqinfo *info =
+ sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+
+ d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
+ d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
+ d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
+ d->dqb_itime = cpu_to_le64(m->dqb_itime);
+ d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
+ d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(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(dquot->dq_id);
+ if (qtree_entry_unused(info, dp))
+ d->dqb_itime = cpu_to_le64(1);
+}
+
+static int v2r1_is_id(void *dp, struct dquot *dquot)
{
- struct v2_disk_dqblk *d = dp;
+ struct v2r1_disk_dqblk *d = dp;
struct qtree_mem_dqinfo *info =
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
diff --git a/fs/quotaio_v2.h b/fs/quotaio_v2.h
index 530fe58..42b916a 100644
--- a/fs/quotaio_v2.h
+++ b/fs/quotaio_v2.h
@@ -17,8 +17,8 @@
}
#define V2_INITQVERSIONS {\
- 0, /* USRQUOTA */\
- 0 /* GRPQUOTA */\
+ 1, /* USRQUOTA */\
+ 1 /* GRPQUOTA */\
}
/* First generic header */
@@ -28,11 +28,11 @@ struct v2_disk_dqheader {
};
/*
- * 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.
+ * The following structure defines the format of the disk quota file in version
+ * 0 - the file is a radix tree whose leaves point to blocks of these
+ * structures.
*/
-struct v2_disk_dqblk {
+struct v2r0_disk_dqblk {
__le32 dqb_id; /* id this quota applies to */
__le32 dqb_ihardlimit; /* absolute limit on allocated inodes */
__le32 dqb_isoftlimit; /* preferred inode limit */
@@ -44,6 +44,20 @@ struct v2_disk_dqblk {
__le64 dqb_itime; /* time limit for excessive inode use */
};
+/* The same structure in quota file version 1 */
+struct v2r1_disk_dqblk {
+ __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 */
+};
+
/* Header with type and version specific information */
struct v2_disk_dqinfo {
__le32 dqi_bgrace; /* Time before block soft limit becomes hard limit */
--
1.5.6
next prev parent reply other threads:[~2008-10-27 12:11 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-27 12:11 [PATCH 00/14] 64-bit quotas and preparations for OCFS2 quotas Jan Kara
2008-10-27 12:11 ` [PATCH 01/14] quota: Add callbacks for allocating and destroying dquot structures Jan Kara
2008-10-27 12:11 ` [PATCH 02/14] quota: Increase size of variables for limits and inode usage Jan Kara
2008-10-27 12:11 ` [PATCH 03/14] quota: Remove bogus 'optimization' in check_idq() and check_bdq() Jan Kara
2008-10-27 12:11 ` [PATCH 04/14] quota: Make _SUSPENDED just a flag Jan Kara
2008-10-27 12:11 ` [PATCH 05/14] quota: Allow to separately enable quota accounting and enforcing limits Jan Kara
2008-10-27 12:11 ` [PATCH 06/14] ext3: Use sb_any_quota_loaded() instead of sb_any_quota_enabled() Jan Kara
2008-10-27 12:11 ` [PATCH 07/14] ext4: " Jan Kara
2008-10-27 12:11 ` [PATCH 08/14] reiserfs: " Jan Kara
2008-10-27 12:11 ` [PATCH 09/14] quota: Remove compatibility function sb_any_quota_enabled() Jan Kara
2008-10-27 12:11 ` [PATCH 10/14] quota: Introduce DQUOT_QUOTA_SYS_FILE flag Jan Kara
2008-10-27 12:11 ` [PATCH 11/14] quota: Move quotaio_v[12].h from include/linux/ to fs/ Jan Kara
2008-10-27 12:11 ` [PATCH 12/14] quota: Split off quota tree handling into a separate file Jan Kara
2008-10-27 12:11 ` [PATCH 13/14] quota: Convert union in mem_dqinfo to a pointer Jan Kara
2008-10-27 12:11 ` Jan Kara [this message]
2008-10-28 5:29 ` [PATCH 14/14] quota: Support 64-bit quota format Andrew Morton
2008-10-29 2:39 ` Jan Kara
2008-10-29 0:41 ` Mingming Cao
2008-10-29 1:02 ` Andrew Morton
2008-10-29 21:31 ` Mingming Cao
2008-10-28 5:55 ` [PATCH 13/14] quota: Convert union in mem_dqinfo to a pointer Andrew Morton
2008-10-29 2:40 ` Jan Kara
2008-10-28 5:52 ` [PATCH 12/14] quota: Split off quota tree handling into a separate file Andrew Morton
2008-10-29 2:43 ` Jan Kara
2008-10-28 22:32 ` [PATCH 11/14] quota: Move quotaio_v[12].h from include/linux/ to fs/ Andrew Morton
2008-10-29 3:21 ` Jan Kara
2008-10-28 5:44 ` [PATCH 10/14] quota: Introduce DQUOT_QUOTA_SYS_FILE flag Andrew Morton
2008-10-28 17:51 ` Joel Becker
2008-10-28 5:40 ` [PATCH 02/14] quota: Increase size of variables for limits and inode usage Andrew Morton
2008-10-28 9:11 ` Boaz Harrosh
2008-10-29 3:01 ` Jan Kara
2008-10-28 5:33 ` [PATCH 01/14] quota: Add callbacks for allocating and destroying dquot structures Andrew Morton
2008-10-29 3:05 ` Jan Kara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1225109513200-git-send-email-jack@suse.cz \
--to=jack@suse.cz \
--cc=akpm@linux-foundation.org \
--cc=andrew.perepechko@sun.com \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.