@@ -23,14 +23,23 @@ MODULE_LICENSE("GPL");
2323
2424#define __QUOTA_V2_PARANOIA
2525
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 ,
3443};
3544
3645#define QUOTABLOCK_BITS 10
@@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
4655 return blocks << QUOTABLOCK_BITS ;
4756}
4857
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+
4974/* Check whether given file is really vfsv0 quotafile */
5075static int v2_check_quota_file (struct super_block * sb , int type )
5176{
5277 struct v2_disk_dqheader dqhead ;
53- ssize_t size ;
5478 static const uint quota_magics [] = V2_INITQMAGICS ;
5579 static const uint quota_versions [] = V2_INITQVERSIONS ;
5680
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 ))
6282 return 0 ;
63- }
6483 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 ])
6685 return 0 ;
6786 return 1 ;
6887}
@@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
7190static int v2_read_file_info (struct super_block * sb , int type )
7291{
7392 struct v2_disk_dqinfo dinfo ;
93+ struct v2_disk_dqheader dqhead ;
7494 struct mem_dqinfo * info = sb_dqinfo (sb , type );
7595 struct qtree_mem_dqinfo * qinfo ;
7696 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 );
77102
78103 size = sb -> s_op -> quota_read (sb , type , (char * )& dinfo ,
79104 sizeof (struct v2_disk_dqinfo ), V2_DQINFOOFF );
80105 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" ,
82107 sb -> s_id );
83108 return -1 ;
84109 }
@@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type)
89114 return -1 ;
90115 }
91116 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+ }
95126 info -> dqi_bgrace = le32_to_cpu (dinfo .dqi_bgrace );
96127 info -> dqi_igrace = le32_to_cpu (dinfo .dqi_igrace );
97128 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)
103134 qinfo -> dqi_blocksize_bits = V2_DQBLKSIZE_BITS ;
104135 qinfo -> dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS ;
105136 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+ }
108144 return 0 ;
109145}
110146
@@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
135171 return 0 ;
136172}
137173
138- static void v2_disk2memdqb (struct dquot * dquot , void * dp )
174+ static void v2r0_disk2memdqb (struct dquot * dquot , void * dp )
139175{
140- struct v2_disk_dqblk * d = dp , empty ;
176+ struct v2r0_disk_dqblk * d = dp , empty ;
141177 struct mem_dqblk * m = & dquot -> dq_dqb ;
142178
143179 m -> dqb_ihardlimit = le32_to_cpu (d -> dqb_ihardlimit );
@@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
149185 m -> dqb_curspace = le64_to_cpu (d -> dqb_curspace );
150186 m -> dqb_btime = le64_to_cpu (d -> dqb_btime );
151187 /* 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 ));
153189 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 )))
155191 m -> dqb_itime = 0 ;
156192}
157193
158- static void v2_mem2diskdqb (void * dp , struct dquot * dquot )
194+ static void v2r0_mem2diskdqb (void * dp , struct dquot * dquot )
159195{
160- struct v2_disk_dqblk * d = dp ;
196+ struct v2r0_disk_dqblk * d = dp ;
161197 struct mem_dqblk * m = & dquot -> dq_dqb ;
162198 struct qtree_mem_dqinfo * info =
163199 sb_dqinfo (dquot -> dq_sb , dquot -> dq_type )-> dqi_priv ;
@@ -175,9 +211,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
175211 d -> dqb_itime = cpu_to_le64 (1 );
176212}
177213
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 )
179266{
180- struct v2_disk_dqblk * d = dp ;
267+ struct v2r1_disk_dqblk * d = dp ;
181268 struct qtree_mem_dqinfo * info =
182269 sb_dqinfo (dquot -> dq_sb , dquot -> dq_type )-> dqi_priv ;
183270
@@ -217,20 +304,32 @@ static const struct quota_format_ops v2_format_ops = {
217304 .release_dqblk = v2_release_dquot ,
218305};
219306
220- static struct quota_format_type v2_quota_format = {
307+ static struct quota_format_type v2r0_quota_format = {
221308 .qf_fmt_id = QFMT_VFS_V0 ,
222309 .qf_ops = & v2_format_ops ,
223310 .qf_owner = THIS_MODULE
224311};
225312
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+
226319static int __init init_v2_quota_format (void )
227320{
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 );
229327}
230328
231329static void __exit exit_v2_quota_format (void )
232330{
233- unregister_quota_format (& v2_quota_format );
331+ unregister_quota_format (& v2r0_quota_format );
332+ unregister_quota_format (& v2r1_quota_format );
234333}
235334
236335module_init (init_v2_quota_format );
0 commit comments