2 * vfsv0 quota IO operations on file
5 #include <linux/errno.h>
7 #include <linux/mount.h>
8 #include <linux/dqblk_v2.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/quotaops.h>
15 #include <asm/byteorder.h>
17 #include "quota_tree.h"
18 #include "quotaio_v2.h"
20 MODULE_AUTHOR("Jan Kara");
21 MODULE_DESCRIPTION("Quota format v2 support");
22 MODULE_LICENSE("GPL");
24 #define __QUOTA_V2_PARANOIA
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
);
33 static const struct qtree_fmt_operations v2r0_qtree_ops
= {
34 .mem2disk_dqblk
= v2r0_mem2diskdqb
,
35 .disk2mem_dqblk
= v2r0_disk2memdqb
,
39 static const struct qtree_fmt_operations v2r1_qtree_ops
= {
40 .mem2disk_dqblk
= v2r1_mem2diskdqb
,
41 .disk2mem_dqblk
= v2r1_disk2memdqb
,
45 #define QUOTABLOCK_BITS 10
46 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
48 static inline qsize_t
v2_stoqb(qsize_t space
)
50 return (space
+ QUOTABLOCK_SIZE
- 1) >> QUOTABLOCK_BITS
;
53 static inline qsize_t
v2_qbtos(qsize_t blocks
)
55 return blocks
<< QUOTABLOCK_BITS
;
58 static int v2_read_header(struct super_block
*sb
, int type
,
59 struct v2_disk_dqheader
*dqhead
)
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 quota_error(sb
, "Failed header read: expected=%zd got=%zd",
67 sizeof(struct v2_disk_dqheader
), size
);
73 /* Check whether given file is really vfsv0 quotafile */
74 static int v2_check_quota_file(struct super_block
*sb
, int type
)
76 struct v2_disk_dqheader dqhead
;
77 static const uint quota_magics
[] = V2_INITQMAGICS
;
78 static const uint quota_versions
[] = V2_INITQVERSIONS
;
80 if (!v2_read_header(sb
, type
, &dqhead
))
82 if (le32_to_cpu(dqhead
.dqh_magic
) != quota_magics
[type
] ||
83 le32_to_cpu(dqhead
.dqh_version
) > quota_versions
[type
])
88 /* Read information header from quota file */
89 static int v2_read_file_info(struct super_block
*sb
, int type
)
91 struct v2_disk_dqinfo dinfo
;
92 struct v2_disk_dqheader dqhead
;
93 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
94 struct qtree_mem_dqinfo
*qinfo
;
98 if (!v2_read_header(sb
, type
, &dqhead
))
100 version
= le32_to_cpu(dqhead
.dqh_version
);
101 if ((info
->dqi_fmt_id
== QFMT_VFS_V0
&& version
!= 0) ||
102 (info
->dqi_fmt_id
== QFMT_VFS_V1
&& version
!= 1))
105 size
= sb
->s_op
->quota_read(sb
, type
, (char *)&dinfo
,
106 sizeof(struct v2_disk_dqinfo
), V2_DQINFOOFF
);
107 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
108 quota_error(sb
, "Can't read info structure");
111 info
->dqi_priv
= kmalloc(sizeof(struct qtree_mem_dqinfo
), GFP_NOFS
);
112 if (!info
->dqi_priv
) {
114 "Not enough memory for quota information structure.\n");
117 qinfo
= info
->dqi_priv
;
119 /* limits are stored as unsigned 32-bit data */
120 info
->dqi_max_spc_limit
= 0xffffffffLL
<< QUOTABLOCK_BITS
;
121 info
->dqi_max_ino_limit
= 0xffffffff;
124 * Used space is stored as unsigned 64-bit value in bytes but
125 * quota core supports only signed 64-bit values so use that
128 info
->dqi_max_spc_limit
= 0x7fffffffffffffffLL
; /* 2^63-1 */
129 info
->dqi_max_ino_limit
= 0x7fffffffffffffffLL
;
131 info
->dqi_bgrace
= le32_to_cpu(dinfo
.dqi_bgrace
);
132 info
->dqi_igrace
= le32_to_cpu(dinfo
.dqi_igrace
);
133 /* No flags currently supported */
136 qinfo
->dqi_type
= type
;
137 qinfo
->dqi_blocks
= le32_to_cpu(dinfo
.dqi_blocks
);
138 qinfo
->dqi_free_blk
= le32_to_cpu(dinfo
.dqi_free_blk
);
139 qinfo
->dqi_free_entry
= le32_to_cpu(dinfo
.dqi_free_entry
);
140 qinfo
->dqi_blocksize_bits
= V2_DQBLKSIZE_BITS
;
141 qinfo
->dqi_usable_bs
= 1 << V2_DQBLKSIZE_BITS
;
142 qinfo
->dqi_qtree_depth
= qtree_depth(qinfo
);
144 qinfo
->dqi_entry_size
= sizeof(struct v2r0_disk_dqblk
);
145 qinfo
->dqi_ops
= &v2r0_qtree_ops
;
147 qinfo
->dqi_entry_size
= sizeof(struct v2r1_disk_dqblk
);
148 qinfo
->dqi_ops
= &v2r1_qtree_ops
;
153 /* Write information header to quota file */
154 static int v2_write_file_info(struct super_block
*sb
, int type
)
156 struct v2_disk_dqinfo dinfo
;
157 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
158 struct qtree_mem_dqinfo
*qinfo
= info
->dqi_priv
;
161 spin_lock(&dq_data_lock
);
162 info
->dqi_flags
&= ~DQF_INFO_DIRTY
;
163 dinfo
.dqi_bgrace
= cpu_to_le32(info
->dqi_bgrace
);
164 dinfo
.dqi_igrace
= cpu_to_le32(info
->dqi_igrace
);
165 /* No flags currently supported */
166 dinfo
.dqi_flags
= cpu_to_le32(0);
167 spin_unlock(&dq_data_lock
);
168 dinfo
.dqi_blocks
= cpu_to_le32(qinfo
->dqi_blocks
);
169 dinfo
.dqi_free_blk
= cpu_to_le32(qinfo
->dqi_free_blk
);
170 dinfo
.dqi_free_entry
= cpu_to_le32(qinfo
->dqi_free_entry
);
171 size
= sb
->s_op
->quota_write(sb
, type
, (char *)&dinfo
,
172 sizeof(struct v2_disk_dqinfo
), V2_DQINFOOFF
);
173 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
174 quota_error(sb
, "Can't write info structure");
180 static void v2r0_disk2memdqb(struct dquot
*dquot
, void *dp
)
182 struct v2r0_disk_dqblk
*d
= dp
, empty
;
183 struct mem_dqblk
*m
= &dquot
->dq_dqb
;
185 m
->dqb_ihardlimit
= le32_to_cpu(d
->dqb_ihardlimit
);
186 m
->dqb_isoftlimit
= le32_to_cpu(d
->dqb_isoftlimit
);
187 m
->dqb_curinodes
= le32_to_cpu(d
->dqb_curinodes
);
188 m
->dqb_itime
= le64_to_cpu(d
->dqb_itime
);
189 m
->dqb_bhardlimit
= v2_qbtos(le32_to_cpu(d
->dqb_bhardlimit
));
190 m
->dqb_bsoftlimit
= v2_qbtos(le32_to_cpu(d
->dqb_bsoftlimit
));
191 m
->dqb_curspace
= le64_to_cpu(d
->dqb_curspace
);
192 m
->dqb_btime
= le64_to_cpu(d
->dqb_btime
);
193 /* We need to escape back all-zero structure */
194 memset(&empty
, 0, sizeof(struct v2r0_disk_dqblk
));
195 empty
.dqb_itime
= cpu_to_le64(1);
196 if (!memcmp(&empty
, dp
, sizeof(struct v2r0_disk_dqblk
)))
200 static void v2r0_mem2diskdqb(void *dp
, struct dquot
*dquot
)
202 struct v2r0_disk_dqblk
*d
= dp
;
203 struct mem_dqblk
*m
= &dquot
->dq_dqb
;
204 struct qtree_mem_dqinfo
*info
=
205 sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
;
207 d
->dqb_ihardlimit
= cpu_to_le32(m
->dqb_ihardlimit
);
208 d
->dqb_isoftlimit
= cpu_to_le32(m
->dqb_isoftlimit
);
209 d
->dqb_curinodes
= cpu_to_le32(m
->dqb_curinodes
);
210 d
->dqb_itime
= cpu_to_le64(m
->dqb_itime
);
211 d
->dqb_bhardlimit
= cpu_to_le32(v2_stoqb(m
->dqb_bhardlimit
));
212 d
->dqb_bsoftlimit
= cpu_to_le32(v2_stoqb(m
->dqb_bsoftlimit
));
213 d
->dqb_curspace
= cpu_to_le64(m
->dqb_curspace
);
214 d
->dqb_btime
= cpu_to_le64(m
->dqb_btime
);
215 d
->dqb_id
= cpu_to_le32(from_kqid(&init_user_ns
, dquot
->dq_id
));
216 if (qtree_entry_unused(info
, dp
))
217 d
->dqb_itime
= cpu_to_le64(1);
220 static int v2r0_is_id(void *dp
, struct dquot
*dquot
)
222 struct v2r0_disk_dqblk
*d
= dp
;
223 struct qtree_mem_dqinfo
*info
=
224 sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
;
226 if (qtree_entry_unused(info
, dp
))
228 return qid_eq(make_kqid(&init_user_ns
, dquot
->dq_id
.type
,
229 le32_to_cpu(d
->dqb_id
)),
233 static void v2r1_disk2memdqb(struct dquot
*dquot
, void *dp
)
235 struct v2r1_disk_dqblk
*d
= dp
, empty
;
236 struct mem_dqblk
*m
= &dquot
->dq_dqb
;
238 m
->dqb_ihardlimit
= le64_to_cpu(d
->dqb_ihardlimit
);
239 m
->dqb_isoftlimit
= le64_to_cpu(d
->dqb_isoftlimit
);
240 m
->dqb_curinodes
= le64_to_cpu(d
->dqb_curinodes
);
241 m
->dqb_itime
= le64_to_cpu(d
->dqb_itime
);
242 m
->dqb_bhardlimit
= v2_qbtos(le64_to_cpu(d
->dqb_bhardlimit
));
243 m
->dqb_bsoftlimit
= v2_qbtos(le64_to_cpu(d
->dqb_bsoftlimit
));
244 m
->dqb_curspace
= le64_to_cpu(d
->dqb_curspace
);
245 m
->dqb_btime
= le64_to_cpu(d
->dqb_btime
);
246 /* We need to escape back all-zero structure */
247 memset(&empty
, 0, sizeof(struct v2r1_disk_dqblk
));
248 empty
.dqb_itime
= cpu_to_le64(1);
249 if (!memcmp(&empty
, dp
, sizeof(struct v2r1_disk_dqblk
)))
253 static void v2r1_mem2diskdqb(void *dp
, struct dquot
*dquot
)
255 struct v2r1_disk_dqblk
*d
= dp
;
256 struct mem_dqblk
*m
= &dquot
->dq_dqb
;
257 struct qtree_mem_dqinfo
*info
=
258 sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
;
260 d
->dqb_ihardlimit
= cpu_to_le64(m
->dqb_ihardlimit
);
261 d
->dqb_isoftlimit
= cpu_to_le64(m
->dqb_isoftlimit
);
262 d
->dqb_curinodes
= cpu_to_le64(m
->dqb_curinodes
);
263 d
->dqb_itime
= cpu_to_le64(m
->dqb_itime
);
264 d
->dqb_bhardlimit
= cpu_to_le64(v2_stoqb(m
->dqb_bhardlimit
));
265 d
->dqb_bsoftlimit
= cpu_to_le64(v2_stoqb(m
->dqb_bsoftlimit
));
266 d
->dqb_curspace
= cpu_to_le64(m
->dqb_curspace
);
267 d
->dqb_btime
= cpu_to_le64(m
->dqb_btime
);
268 d
->dqb_id
= cpu_to_le32(from_kqid(&init_user_ns
, dquot
->dq_id
));
269 if (qtree_entry_unused(info
, dp
))
270 d
->dqb_itime
= cpu_to_le64(1);
273 static int v2r1_is_id(void *dp
, struct dquot
*dquot
)
275 struct v2r1_disk_dqblk
*d
= dp
;
276 struct qtree_mem_dqinfo
*info
=
277 sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
;
279 if (qtree_entry_unused(info
, dp
))
281 return qid_eq(make_kqid(&init_user_ns
, dquot
->dq_id
.type
,
282 le32_to_cpu(d
->dqb_id
)),
286 static int v2_read_dquot(struct dquot
*dquot
)
288 return qtree_read_dquot(sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
, dquot
);
291 static int v2_write_dquot(struct dquot
*dquot
)
293 return qtree_write_dquot(sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
, dquot
);
296 static int v2_release_dquot(struct dquot
*dquot
)
298 return qtree_release_dquot(sb_dqinfo(dquot
->dq_sb
, dquot
->dq_id
.type
)->dqi_priv
, dquot
);
301 static int v2_free_file_info(struct super_block
*sb
, int type
)
303 kfree(sb_dqinfo(sb
, type
)->dqi_priv
);
307 static int v2_get_next_id(struct super_block
*sb
, struct kqid
*qid
)
309 return qtree_get_next_id(sb_dqinfo(sb
, qid
->type
)->dqi_priv
, qid
);
312 static const struct quota_format_ops v2_format_ops
= {
313 .check_quota_file
= v2_check_quota_file
,
314 .read_file_info
= v2_read_file_info
,
315 .write_file_info
= v2_write_file_info
,
316 .free_file_info
= v2_free_file_info
,
317 .read_dqblk
= v2_read_dquot
,
318 .commit_dqblk
= v2_write_dquot
,
319 .release_dqblk
= v2_release_dquot
,
320 .get_next_id
= v2_get_next_id
,
323 static struct quota_format_type v2r0_quota_format
= {
324 .qf_fmt_id
= QFMT_VFS_V0
,
325 .qf_ops
= &v2_format_ops
,
326 .qf_owner
= THIS_MODULE
329 static struct quota_format_type v2r1_quota_format
= {
330 .qf_fmt_id
= QFMT_VFS_V1
,
331 .qf_ops
= &v2_format_ops
,
332 .qf_owner
= THIS_MODULE
335 static int __init
init_v2_quota_format(void)
339 ret
= register_quota_format(&v2r0_quota_format
);
342 return register_quota_format(&v2r1_quota_format
);
345 static void __exit
exit_v2_quota_format(void)
347 unregister_quota_format(&v2r0_quota_format
);
348 unregister_quota_format(&v2r1_quota_format
);
351 module_init(init_v2_quota_format
);
352 module_exit(exit_v2_quota_format
);