@@ -23,14 +23,23 @@ MODULE_LICENSE("GPL");
23
23
24
24
#define __QUOTA_V2_PARANOIA
25
25
26
- static void v2_mem2diskdqb (void * dp , struct dquot * dquot );
27
- static void v2_disk2memdqb (struct dquot * dquot , void * dp );
28
- static int v2_is_id (void * dp , struct dquot * dquot );
29
-
30
- static struct qtree_fmt_operations v2_qtree_ops = {
31
- .mem2disk_dqblk = v2_mem2diskdqb ,
32
- .disk2mem_dqblk = v2_disk2memdqb ,
33
- .is_id = v2_is_id ,
26
+ static void v2r0_mem2diskdqb (void * dp , struct dquot * dquot );
27
+ static void v2r0_disk2memdqb (struct dquot * dquot , void * dp );
28
+ static int v2r0_is_id (void * dp , struct dquot * dquot );
29
+ static void v2r1_mem2diskdqb (void * dp , struct dquot * dquot );
30
+ static void v2r1_disk2memdqb (struct dquot * dquot , void * dp );
31
+ static int v2r1_is_id (void * dp , struct dquot * dquot );
32
+
33
+ static 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
+
39
+ static 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
45
#define QUOTABLOCK_BITS 10
@@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
46
55
return blocks << QUOTABLOCK_BITS ;
47
56
}
48
57
58
+ static 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
74
/* Check whether given file is really vfsv0 quotafile */
50
75
static int v2_check_quota_file (struct super_block * sb , int type )
51
76
{
52
77
struct v2_disk_dqheader dqhead ;
53
- ssize_t size ;
54
78
static const uint quota_magics [] = V2_INITQMAGICS ;
55
79
static const uint quota_versions [] = V2_INITQVERSIONS ;
56
80
57
- size = sb -> s_op -> quota_read (sb , type , (char * )& 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 );
81
+ if (!v2_read_header (sb , type , & dqhead ))
62
82
return 0 ;
63
- }
64
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
85
return 0 ;
67
86
return 1 ;
68
87
}
@@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
71
90
static int v2_read_file_info (struct super_block * sb , int type )
72
91
{
73
92
struct v2_disk_dqinfo dinfo ;
93
+ struct v2_disk_dqheader dqhead ;
74
94
struct mem_dqinfo * info = sb_dqinfo (sb , type );
75
95
struct qtree_mem_dqinfo * qinfo ;
76
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
103
size = sb -> s_op -> quota_read (sb , type , (char * )& dinfo ,
79
104
sizeof (struct v2_disk_dqinfo ), V2_DQINFOOFF );
80
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
107
sb -> s_id );
83
108
return -1 ;
84
109
}
@@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type)
89
114
return -1 ;
90
115
}
91
116
qinfo = info -> dqi_priv ;
92
- /* limits are stored as unsigned 32-bit data */
93
- info -> dqi_maxblimit = 0xffffffff ;
94
- info -> dqi_maxilimit = 0xffffffff ;
117
+ if (version == 0 ) {
118
+ /* limits are stored as unsigned 32-bit data */
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
126
info -> dqi_bgrace = le32_to_cpu (dinfo .dqi_bgrace );
96
127
info -> dqi_igrace = le32_to_cpu (dinfo .dqi_igrace );
97
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
134
qinfo -> dqi_blocksize_bits = V2_DQBLKSIZE_BITS ;
104
135
qinfo -> dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS ;
105
136
qinfo -> dqi_qtree_depth = qtree_depth (qinfo );
106
- qinfo -> dqi_entry_size = sizeof (struct v2_disk_dqblk );
107
- qinfo -> dqi_ops = & v2_qtree_ops ;
137
+ if (version == 0 ) {
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
144
return 0 ;
109
145
}
110
146
@@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
135
171
return 0 ;
136
172
}
137
173
138
- static void v2_disk2memdqb (struct dquot * dquot , void * dp )
174
+ static 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
177
struct mem_dqblk * m = & dquot -> dq_dqb ;
142
178
143
179
m -> dqb_ihardlimit = le32_to_cpu (d -> dqb_ihardlimit );
@@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
149
185
m -> dqb_curspace = le64_to_cpu (d -> dqb_curspace );
150
186
m -> dqb_btime = le64_to_cpu (d -> dqb_btime );
151
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
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
191
m -> dqb_itime = 0 ;
156
192
}
157
193
158
- static void v2_mem2diskdqb (void * dp , struct dquot * dquot )
194
+ static 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
197
struct mem_dqblk * m = & dquot -> dq_dqb ;
162
198
struct qtree_mem_dqinfo * info =
163
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
211
d -> dqb_itime = cpu_to_le64 (1 );
176
212
}
177
213
178
- static int v2_is_id (void * dp , struct dquot * dquot )
214
+ static 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
+
225
+ static 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
+
245
+ static 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
+
265
+ static 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
268
struct qtree_mem_dqinfo * info =
182
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
304
.release_dqblk = v2_release_dquot ,
218
305
};
219
306
220
- static struct quota_format_type v2_quota_format = {
307
+ static struct quota_format_type v2r0_quota_format = {
221
308
.qf_fmt_id = QFMT_VFS_V0 ,
222
309
.qf_ops = & v2_format_ops ,
223
310
.qf_owner = THIS_MODULE
224
311
};
225
312
313
+ static 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
+
226
319
static 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
231
329
static 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
236
335
module_init (init_v2_quota_format );
0 commit comments