aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota/quota_v2.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-11-16 12:09:47 -0500
committerJan Kara <jack@suse.cz>2009-12-10 09:02:54 -0500
commit498c60153ebb8889d8944591383c5c12af1127d4 (patch)
treecda08502f8aac382fa46893da3c1c1db116c7164 /fs/quota/quota_v2.c
parent30673930051e5203d0b826b8b8f2454cab453b94 (diff)
quota: Implement quota format with 64-bit space and inode limits
So far the maximum quota space limit was 4TB. Apparently this isn't enough for Lustre guys anymore. So implement new quota format which raises block limits to 2^64 bytes. Also store number of inodes and inode limits in 64-bit variables as 2^32 files isn't that insanely high anymore. The first version of the patch has been developed by Andrew Perepechko <Andrew.Perepechko@Sun.COM>. CC: Andrew.Perepechko@Sun.COM Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota/quota_v2.c')
-rw-r--r--fs/quota/quota_v2.c165
1 files changed, 132 insertions, 33 deletions
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c
index 01f25eae684d..3dfc23e02135 100644
--- a/fs/quota/quota_v2.c
+++ b/fs/quota/quota_v2.c
@@ -23,14 +23,23 @@ MODULE_LICENSE("GPL");
23 23
24#define __QUOTA_V2_PARANOIA 24#define __QUOTA_V2_PARANOIA
25 25
26static void v2_mem2diskdqb(void *dp, struct dquot *dquot); 26static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
27static void v2_disk2memdqb(struct dquot *dquot, void *dp); 27static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
28static int v2_is_id(void *dp, struct dquot *dquot); 28static int v2r0_is_id(void *dp, struct dquot *dquot);
29 29static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
30static struct qtree_fmt_operations v2_qtree_ops = { 30static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
31 .mem2disk_dqblk = v2_mem2diskdqb, 31static int v2r1_is_id(void *dp, struct dquot *dquot);
32 .disk2mem_dqblk = v2_disk2memdqb, 32
33 .is_id = v2_is_id, 33static struct qtree_fmt_operations v2r0_qtree_ops = {
34 .mem2disk_dqblk = v2r0_mem2diskdqb,
35 .disk2mem_dqblk = v2r0_disk2memdqb,
36 .is_id = v2r0_is_id,
37};
38
39static struct qtree_fmt_operations v2r1_qtree_ops = {
40 .mem2disk_dqblk = v2r1_mem2diskdqb,
41 .disk2mem_dqblk = v2r1_disk2memdqb,
42 .is_id = v2r1_is_id,
34}; 43};
35 44
36#define QUOTABLOCK_BITS 10 45#define QUOTABLOCK_BITS 10
@@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
46 return blocks << QUOTABLOCK_BITS; 55 return blocks << QUOTABLOCK_BITS;
47} 56}
48 57
58static int v2_read_header(struct super_block *sb, int type,
59 struct v2_disk_dqheader *dqhead)
60{
61 ssize_t size;
62
63 size = sb->s_op->quota_read(sb, type, (char *)dqhead,
64 sizeof(struct v2_disk_dqheader), 0);
65 if (size != sizeof(struct v2_disk_dqheader)) {
66 printk(KERN_WARNING "quota_v2: Failed header read:"
67 " expected=%zd got=%zd\n",
68 sizeof(struct v2_disk_dqheader), size);
69 return 0;
70 }
71 return 1;
72}
73
49/* Check whether given file is really vfsv0 quotafile */ 74/* Check whether given file is really vfsv0 quotafile */
50static int v2_check_quota_file(struct super_block *sb, int type) 75static int v2_check_quota_file(struct super_block *sb, int type)
51{ 76{
52 struct v2_disk_dqheader dqhead; 77 struct v2_disk_dqheader dqhead;
53 ssize_t size;
54 static const uint quota_magics[] = V2_INITQMAGICS; 78 static const uint quota_magics[] = V2_INITQMAGICS;
55 static const uint quota_versions[] = V2_INITQVERSIONS; 79 static const uint quota_versions[] = V2_INITQVERSIONS;
56 80
57 size = sb->s_op->quota_read(sb, type, (char *)&dqhead, 81 if (!v2_read_header(sb, type, &dqhead))
58 sizeof(struct v2_disk_dqheader), 0);
59 if (size != sizeof(struct v2_disk_dqheader)) {
60 printk("quota_v2: failed read expected=%zd got=%zd\n",
61 sizeof(struct v2_disk_dqheader), size);
62 return 0; 82 return 0;
63 }
64 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || 83 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
65 le32_to_cpu(dqhead.dqh_version) != quota_versions[type]) 84 le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
66 return 0; 85 return 0;
67 return 1; 86 return 1;
68} 87}
@@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
71static int v2_read_file_info(struct super_block *sb, int type) 90static int v2_read_file_info(struct super_block *sb, int type)
72{ 91{
73 struct v2_disk_dqinfo dinfo; 92 struct v2_disk_dqinfo dinfo;
93 struct v2_disk_dqheader dqhead;
74 struct mem_dqinfo *info = sb_dqinfo(sb, type); 94 struct mem_dqinfo *info = sb_dqinfo(sb, type);
75 struct qtree_mem_dqinfo *qinfo; 95 struct qtree_mem_dqinfo *qinfo;
76 ssize_t size; 96 ssize_t size;
97 unsigned int version;
98
99 if (!v2_read_header(sb, type, &dqhead))
100 return 0;
101 version = le32_to_cpu(dqhead.dqh_version);
77 102
78 size = sb->s_op->quota_read(sb, type, (char *)&dinfo, 103 size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
79 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); 104 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
80 if (size != sizeof(struct v2_disk_dqinfo)) { 105 if (size != sizeof(struct v2_disk_dqinfo)) {
81 printk(KERN_WARNING "Can't read info structure on device %s.\n", 106 printk(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n",
82 sb->s_id); 107 sb->s_id);
83 return -1; 108 return -1;
84 } 109 }
@@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type)
89 return -1; 114 return -1;
90 } 115 }
91 qinfo = info->dqi_priv; 116 qinfo = info->dqi_priv;
92 /* limits are stored as unsigned 32-bit data */ 117 if (version == 0) {
93 info->dqi_maxblimit = 0xffffffff; 118 /* limits are stored as unsigned 32-bit data */
94 info->dqi_maxilimit = 0xffffffff; 119 info->dqi_maxblimit = 0xffffffff;
120 info->dqi_maxilimit = 0xffffffff;
121 } else {
122 /* used space is stored as unsigned 64-bit value */
123 info->dqi_maxblimit = 0xffffffffffffffff; /* 2^64-1 */
124 info->dqi_maxilimit = 0xffffffffffffffff;
125 }
95 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); 126 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
96 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); 127 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
97 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); 128 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
@@ -103,8 +134,13 @@ static int v2_read_file_info(struct super_block *sb, int type)
103 qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS; 134 qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
104 qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS; 135 qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
105 qinfo->dqi_qtree_depth = qtree_depth(qinfo); 136 qinfo->dqi_qtree_depth = qtree_depth(qinfo);
106 qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk); 137 if (version == 0) {
107 qinfo->dqi_ops = &v2_qtree_ops; 138 qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
139 qinfo->dqi_ops = &v2r0_qtree_ops;
140 } else {
141 qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
142 qinfo->dqi_ops = &v2r1_qtree_ops;
143 }
108 return 0; 144 return 0;
109} 145}
110 146
@@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
135 return 0; 171 return 0;
136} 172}
137 173
138static void v2_disk2memdqb(struct dquot *dquot, void *dp) 174static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
139{ 175{
140 struct v2_disk_dqblk *d = dp, empty; 176 struct v2r0_disk_dqblk *d = dp, empty;
141 struct mem_dqblk *m = &dquot->dq_dqb; 177 struct mem_dqblk *m = &dquot->dq_dqb;
142 178
143 m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit); 179 m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
@@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
149 m->dqb_curspace = le64_to_cpu(d->dqb_curspace); 185 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
150 m->dqb_btime = le64_to_cpu(d->dqb_btime); 186 m->dqb_btime = le64_to_cpu(d->dqb_btime);
151 /* We need to escape back all-zero structure */ 187 /* We need to escape back all-zero structure */
152 memset(&empty, 0, sizeof(struct v2_disk_dqblk)); 188 memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
153 empty.dqb_itime = cpu_to_le64(1); 189 empty.dqb_itime = cpu_to_le64(1);
154 if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk))) 190 if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
155 m->dqb_itime = 0; 191 m->dqb_itime = 0;
156} 192}
157 193
158static void v2_mem2diskdqb(void *dp, struct dquot *dquot) 194static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
159{ 195{
160 struct v2_disk_dqblk *d = dp; 196 struct v2r0_disk_dqblk *d = dp;
161 struct mem_dqblk *m = &dquot->dq_dqb; 197 struct mem_dqblk *m = &dquot->dq_dqb;
162 struct qtree_mem_dqinfo *info = 198 struct qtree_mem_dqinfo *info =
163 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; 199 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
@@ -175,9 +211,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
175 d->dqb_itime = cpu_to_le64(1); 211 d->dqb_itime = cpu_to_le64(1);
176} 212}
177 213
178static int v2_is_id(void *dp, struct dquot *dquot) 214static int v2r0_is_id(void *dp, struct dquot *dquot)
215{
216 struct v2r0_disk_dqblk *d = dp;
217 struct qtree_mem_dqinfo *info =
218 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
219
220 if (qtree_entry_unused(info, dp))
221 return 0;
222 return le32_to_cpu(d->dqb_id) == dquot->dq_id;
223}
224
225static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
226{
227 struct v2r1_disk_dqblk *d = dp, empty;
228 struct mem_dqblk *m = &dquot->dq_dqb;
229
230 m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
231 m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
232 m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
233 m->dqb_itime = le64_to_cpu(d->dqb_itime);
234 m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
235 m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
236 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
237 m->dqb_btime = le64_to_cpu(d->dqb_btime);
238 /* We need to escape back all-zero structure */
239 memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
240 empty.dqb_itime = cpu_to_le64(1);
241 if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
242 m->dqb_itime = 0;
243}
244
245static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
246{
247 struct v2r1_disk_dqblk *d = dp;
248 struct mem_dqblk *m = &dquot->dq_dqb;
249 struct qtree_mem_dqinfo *info =
250 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
251
252 d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
253 d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
254 d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
255 d->dqb_itime = cpu_to_le64(m->dqb_itime);
256 d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
257 d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
258 d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
259 d->dqb_btime = cpu_to_le64(m->dqb_btime);
260 d->dqb_id = cpu_to_le32(dquot->dq_id);
261 if (qtree_entry_unused(info, dp))
262 d->dqb_itime = cpu_to_le64(1);
263}
264
265static int v2r1_is_id(void *dp, struct dquot *dquot)
179{ 266{
180 struct v2_disk_dqblk *d = dp; 267 struct v2r1_disk_dqblk *d = dp;
181 struct qtree_mem_dqinfo *info = 268 struct qtree_mem_dqinfo *info =
182 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; 269 sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
183 270
@@ -217,20 +304,32 @@ static const struct quota_format_ops v2_format_ops = {
217 .release_dqblk = v2_release_dquot, 304 .release_dqblk = v2_release_dquot,
218}; 305};
219 306
220static struct quota_format_type v2_quota_format = { 307static struct quota_format_type v2r0_quota_format = {
221 .qf_fmt_id = QFMT_VFS_V0, 308 .qf_fmt_id = QFMT_VFS_V0,
222 .qf_ops = &v2_format_ops, 309 .qf_ops = &v2_format_ops,
223 .qf_owner = THIS_MODULE 310 .qf_owner = THIS_MODULE
224}; 311};
225 312
313static struct quota_format_type v2r1_quota_format = {
314 .qf_fmt_id = QFMT_VFS_V1,
315 .qf_ops = &v2_format_ops,
316 .qf_owner = THIS_MODULE
317};
318
226static int __init init_v2_quota_format(void) 319static int __init init_v2_quota_format(void)
227{ 320{
228 return register_quota_format(&v2_quota_format); 321 int ret;
322
323 ret = register_quota_format(&v2r0_quota_format);
324 if (ret)
325 return ret;
326 return register_quota_format(&v2r1_quota_format);
229} 327}
230 328
231static void __exit exit_v2_quota_format(void) 329static void __exit exit_v2_quota_format(void)
232{ 330{
233 unregister_quota_format(&v2_quota_format); 331 unregister_quota_format(&v2r0_quota_format);
332 unregister_quota_format(&v2r1_quota_format);
234} 333}
235 334
236module_init(init_v2_quota_format); 335module_init(init_v2_quota_format);