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 "quotaio_v2.h"
19 MODULE_AUTHOR("Jan Kara");
20 MODULE_DESCRIPTION("Quota format v2 support");
21 MODULE_LICENSE("GPL");
23 #define __QUOTA_V2_PARANOIA
25 typedef char *dqbuf_t
;
27 #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
28 #define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
30 #define QUOTABLOCK_BITS 10
31 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
33 static inline qsize_t
v2_stoqb(qsize_t space
)
35 return (space
+ QUOTABLOCK_SIZE
- 1) >> QUOTABLOCK_BITS
;
38 static inline qsize_t
v2_qbtos(qsize_t blocks
)
40 return blocks
<< QUOTABLOCK_BITS
;
43 /* Check whether given file is really vfsv0 quotafile */
44 static int v2_check_quota_file(struct super_block
*sb
, int type
)
46 struct v2_disk_dqheader dqhead
;
48 static const uint quota_magics
[] = V2_INITQMAGICS
;
49 static const uint quota_versions
[] = V2_INITQVERSIONS
;
51 size
= sb
->s_op
->quota_read(sb
, type
, (char *)&dqhead
, sizeof(struct v2_disk_dqheader
), 0);
52 if (size
!= sizeof(struct v2_disk_dqheader
)) {
53 printk("quota_v2: failed read expected=%zd got=%zd\n",
54 sizeof(struct v2_disk_dqheader
), size
);
57 if (le32_to_cpu(dqhead
.dqh_magic
) != quota_magics
[type
] ||
58 le32_to_cpu(dqhead
.dqh_version
) != quota_versions
[type
])
63 /* Read information header from quota file */
64 static int v2_read_file_info(struct super_block
*sb
, int type
)
66 struct v2_disk_dqinfo dinfo
;
67 struct mem_dqinfo
*info
= sb_dqopt(sb
)->info
+type
;
70 size
= sb
->s_op
->quota_read(sb
, type
, (char *)&dinfo
,
71 sizeof(struct v2_disk_dqinfo
), V2_DQINFOOFF
);
72 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
73 printk(KERN_WARNING
"Can't read info structure on device %s.\n",
77 /* limits are stored as unsigned 32-bit data */
78 info
->dqi_maxblimit
= 0xffffffff;
79 info
->dqi_maxilimit
= 0xffffffff;
80 info
->dqi_bgrace
= le32_to_cpu(dinfo
.dqi_bgrace
);
81 info
->dqi_igrace
= le32_to_cpu(dinfo
.dqi_igrace
);
82 info
->dqi_flags
= le32_to_cpu(dinfo
.dqi_flags
);
83 info
->u
.v2_i
.dqi_blocks
= le32_to_cpu(dinfo
.dqi_blocks
);
84 info
->u
.v2_i
.dqi_free_blk
= le32_to_cpu(dinfo
.dqi_free_blk
);
85 info
->u
.v2_i
.dqi_free_entry
= le32_to_cpu(dinfo
.dqi_free_entry
);
89 /* Write information header to quota file */
90 static int v2_write_file_info(struct super_block
*sb
, int type
)
92 struct v2_disk_dqinfo dinfo
;
93 struct mem_dqinfo
*info
= sb_dqopt(sb
)->info
+type
;
96 spin_lock(&dq_data_lock
);
97 info
->dqi_flags
&= ~DQF_INFO_DIRTY
;
98 dinfo
.dqi_bgrace
= cpu_to_le32(info
->dqi_bgrace
);
99 dinfo
.dqi_igrace
= cpu_to_le32(info
->dqi_igrace
);
100 dinfo
.dqi_flags
= cpu_to_le32(info
->dqi_flags
& DQF_MASK
);
101 spin_unlock(&dq_data_lock
);
102 dinfo
.dqi_blocks
= cpu_to_le32(info
->u
.v2_i
.dqi_blocks
);
103 dinfo
.dqi_free_blk
= cpu_to_le32(info
->u
.v2_i
.dqi_free_blk
);
104 dinfo
.dqi_free_entry
= cpu_to_le32(info
->u
.v2_i
.dqi_free_entry
);
105 size
= sb
->s_op
->quota_write(sb
, type
, (char *)&dinfo
,
106 sizeof(struct v2_disk_dqinfo
), V2_DQINFOOFF
);
107 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
108 printk(KERN_WARNING
"Can't write info structure on device %s.\n",
115 static void disk2memdqb(struct mem_dqblk
*m
, struct v2_disk_dqblk
*d
)
117 m
->dqb_ihardlimit
= le32_to_cpu(d
->dqb_ihardlimit
);
118 m
->dqb_isoftlimit
= le32_to_cpu(d
->dqb_isoftlimit
);
119 m
->dqb_curinodes
= le32_to_cpu(d
->dqb_curinodes
);
120 m
->dqb_itime
= le64_to_cpu(d
->dqb_itime
);
121 m
->dqb_bhardlimit
= v2_qbtos(le32_to_cpu(d
->dqb_bhardlimit
));
122 m
->dqb_bsoftlimit
= v2_qbtos(le32_to_cpu(d
->dqb_bsoftlimit
));
123 m
->dqb_curspace
= le64_to_cpu(d
->dqb_curspace
);
124 m
->dqb_btime
= le64_to_cpu(d
->dqb_btime
);
127 static void mem2diskdqb(struct v2_disk_dqblk
*d
, struct mem_dqblk
*m
, qid_t id
)
129 d
->dqb_ihardlimit
= cpu_to_le32(m
->dqb_ihardlimit
);
130 d
->dqb_isoftlimit
= cpu_to_le32(m
->dqb_isoftlimit
);
131 d
->dqb_curinodes
= cpu_to_le32(m
->dqb_curinodes
);
132 d
->dqb_itime
= cpu_to_le64(m
->dqb_itime
);
133 d
->dqb_bhardlimit
= cpu_to_le32(v2_stoqb(m
->dqb_bhardlimit
));
134 d
->dqb_bsoftlimit
= cpu_to_le32(v2_stoqb(m
->dqb_bsoftlimit
));
135 d
->dqb_curspace
= cpu_to_le64(m
->dqb_curspace
);
136 d
->dqb_btime
= cpu_to_le64(m
->dqb_btime
);
137 d
->dqb_id
= cpu_to_le32(id
);
140 static dqbuf_t
getdqbuf(void)
142 dqbuf_t buf
= kmalloc(V2_DQBLKSIZE
, GFP_NOFS
);
144 printk(KERN_WARNING
"VFS: Not enough memory for quota buffers.\n");
148 static inline void freedqbuf(dqbuf_t buf
)
153 static inline ssize_t
read_blk(struct super_block
*sb
, int type
, uint blk
, dqbuf_t buf
)
155 memset(buf
, 0, V2_DQBLKSIZE
);
156 return sb
->s_op
->quota_read(sb
, type
, (char *)buf
,
157 V2_DQBLKSIZE
, blk
<< V2_DQBLKSIZE_BITS
);
160 static inline ssize_t
write_blk(struct super_block
*sb
, int type
, uint blk
, dqbuf_t buf
)
162 return sb
->s_op
->quota_write(sb
, type
, (char *)buf
,
163 V2_DQBLKSIZE
, blk
<< V2_DQBLKSIZE_BITS
);
166 /* Remove empty block from list and return it */
167 static int get_free_dqblk(struct super_block
*sb
, int type
)
169 dqbuf_t buf
= getdqbuf();
170 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
171 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
176 if (info
->u
.v2_i
.dqi_free_blk
) {
177 blk
= info
->u
.v2_i
.dqi_free_blk
;
178 if ((ret
= read_blk(sb
, type
, blk
, buf
)) < 0)
180 info
->u
.v2_i
.dqi_free_blk
= le32_to_cpu(dh
->dqdh_next_free
);
183 memset(buf
, 0, V2_DQBLKSIZE
);
184 /* Assure block allocation... */
185 if ((ret
= write_blk(sb
, type
, info
->u
.v2_i
.dqi_blocks
, buf
)) < 0)
187 blk
= info
->u
.v2_i
.dqi_blocks
++;
189 mark_info_dirty(sb
, type
);
196 /* Insert empty block to the list */
197 static int put_free_dqblk(struct super_block
*sb
, int type
, dqbuf_t buf
, uint blk
)
199 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
200 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
203 dh
->dqdh_next_free
= cpu_to_le32(info
->u
.v2_i
.dqi_free_blk
);
204 dh
->dqdh_prev_free
= cpu_to_le32(0);
205 dh
->dqdh_entries
= cpu_to_le16(0);
206 info
->u
.v2_i
.dqi_free_blk
= blk
;
207 mark_info_dirty(sb
, type
);
208 /* Some strange block. We had better leave it... */
209 if ((err
= write_blk(sb
, type
, blk
, buf
)) < 0)
214 /* Remove given block from the list of blocks with free entries */
215 static int remove_free_dqentry(struct super_block
*sb
, int type
, dqbuf_t buf
, uint blk
)
217 dqbuf_t tmpbuf
= getdqbuf();
218 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
219 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
220 uint nextblk
= le32_to_cpu(dh
->dqdh_next_free
), prevblk
= le32_to_cpu(dh
->dqdh_prev_free
);
226 if ((err
= read_blk(sb
, type
, nextblk
, tmpbuf
)) < 0)
228 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_prev_free
= dh
->dqdh_prev_free
;
229 if ((err
= write_blk(sb
, type
, nextblk
, tmpbuf
)) < 0)
233 if ((err
= read_blk(sb
, type
, prevblk
, tmpbuf
)) < 0)
235 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_next_free
= dh
->dqdh_next_free
;
236 if ((err
= write_blk(sb
, type
, prevblk
, tmpbuf
)) < 0)
240 info
->u
.v2_i
.dqi_free_entry
= nextblk
;
241 mark_info_dirty(sb
, type
);
244 dh
->dqdh_next_free
= dh
->dqdh_prev_free
= cpu_to_le32(0);
245 /* No matter whether write succeeds block is out of list */
246 if (write_blk(sb
, type
, blk
, buf
) < 0)
247 printk(KERN_ERR
"VFS: Can't write block (%u) with free entries.\n", blk
);
254 /* Insert given block to the beginning of list with free entries */
255 static int insert_free_dqentry(struct super_block
*sb
, int type
, dqbuf_t buf
, uint blk
)
257 dqbuf_t tmpbuf
= getdqbuf();
258 struct mem_dqinfo
*info
= sb_dqinfo(sb
, type
);
259 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
264 dh
->dqdh_next_free
= cpu_to_le32(info
->u
.v2_i
.dqi_free_entry
);
265 dh
->dqdh_prev_free
= cpu_to_le32(0);
266 if ((err
= write_blk(sb
, type
, blk
, buf
)) < 0)
268 if (info
->u
.v2_i
.dqi_free_entry
) {
269 if ((err
= read_blk(sb
, type
, info
->u
.v2_i
.dqi_free_entry
, tmpbuf
)) < 0)
271 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_prev_free
= cpu_to_le32(blk
);
272 if ((err
= write_blk(sb
, type
, info
->u
.v2_i
.dqi_free_entry
, tmpbuf
)) < 0)
276 info
->u
.v2_i
.dqi_free_entry
= blk
;
277 mark_info_dirty(sb
, type
);
284 /* Find space for dquot */
285 static uint
find_free_dqentry(struct dquot
*dquot
, int *err
)
287 struct super_block
*sb
= dquot
->dq_sb
;
288 struct mem_dqinfo
*info
= sb_dqopt(sb
)->info
+dquot
->dq_type
;
290 struct v2_disk_dqdbheader
*dh
;
291 struct v2_disk_dqblk
*ddquot
;
292 struct v2_disk_dqblk fakedquot
;
296 if (!(buf
= getdqbuf())) {
300 dh
= (struct v2_disk_dqdbheader
*)buf
;
301 ddquot
= GETENTRIES(buf
);
302 if (info
->u
.v2_i
.dqi_free_entry
) {
303 blk
= info
->u
.v2_i
.dqi_free_entry
;
304 if ((*err
= read_blk(sb
, dquot
->dq_type
, blk
, buf
)) < 0)
308 blk
= get_free_dqblk(sb
, dquot
->dq_type
);
314 memset(buf
, 0, V2_DQBLKSIZE
);
315 /* This is enough as block is already zeroed and entry list is empty... */
316 info
->u
.v2_i
.dqi_free_entry
= blk
;
317 mark_info_dirty(sb
, dquot
->dq_type
);
319 if (le16_to_cpu(dh
->dqdh_entries
)+1 >= V2_DQSTRINBLK
) /* Block will be full? */
320 if ((*err
= remove_free_dqentry(sb
, dquot
->dq_type
, buf
, blk
)) < 0) {
321 printk(KERN_ERR
"VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk
);
324 le16_add_cpu(&dh
->dqdh_entries
, 1);
325 memset(&fakedquot
, 0, sizeof(struct v2_disk_dqblk
));
326 /* Find free structure in block */
327 for (i
= 0; i
< V2_DQSTRINBLK
&& memcmp(&fakedquot
, ddquot
+i
, sizeof(struct v2_disk_dqblk
)); i
++);
328 #ifdef __QUOTA_V2_PARANOIA
329 if (i
== V2_DQSTRINBLK
) {
330 printk(KERN_ERR
"VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
335 if ((*err
= write_blk(sb
, dquot
->dq_type
, blk
, buf
)) < 0) {
336 printk(KERN_ERR
"VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk
);
339 dquot
->dq_off
= (blk
<<V2_DQBLKSIZE_BITS
)+sizeof(struct v2_disk_dqdbheader
)+i
*sizeof(struct v2_disk_dqblk
);
347 /* Insert reference to structure into the trie */
348 static int do_insert_tree(struct dquot
*dquot
, uint
*treeblk
, int depth
)
350 struct super_block
*sb
= dquot
->dq_sb
;
352 int ret
= 0, newson
= 0, newact
= 0;
356 if (!(buf
= getdqbuf()))
359 ret
= get_free_dqblk(sb
, dquot
->dq_type
);
363 memset(buf
, 0, V2_DQBLKSIZE
);
367 if ((ret
= read_blk(sb
, dquot
->dq_type
, *treeblk
, buf
)) < 0) {
368 printk(KERN_ERR
"VFS: Can't read tree quota block %u.\n", *treeblk
);
373 newblk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
376 if (depth
== V2_DQTREEDEPTH
-1) {
377 #ifdef __QUOTA_V2_PARANOIA
379 printk(KERN_ERR
"VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]));
384 newblk
= find_free_dqentry(dquot
, &ret
);
387 ret
= do_insert_tree(dquot
, &newblk
, depth
+1);
388 if (newson
&& ret
>= 0) {
389 ref
[GETIDINDEX(dquot
->dq_id
, depth
)] = cpu_to_le32(newblk
);
390 ret
= write_blk(sb
, dquot
->dq_type
, *treeblk
, buf
);
392 else if (newact
&& ret
< 0)
393 put_free_dqblk(sb
, dquot
->dq_type
, buf
, *treeblk
);
399 /* Wrapper for inserting quota structure into tree */
400 static inline int dq_insert_tree(struct dquot
*dquot
)
402 int tmp
= V2_DQTREEOFF
;
403 return do_insert_tree(dquot
, &tmp
, 0);
407 * We don't have to be afraid of deadlocks as we never have quotas on quota files...
409 static int v2_write_dquot(struct dquot
*dquot
)
411 int type
= dquot
->dq_type
;
413 struct v2_disk_dqblk ddquot
, empty
;
415 /* dq_off is guarded by dqio_mutex */
417 if ((ret
= dq_insert_tree(dquot
)) < 0) {
418 printk(KERN_ERR
"VFS: Error %zd occurred while creating quota.\n", ret
);
421 spin_lock(&dq_data_lock
);
422 mem2diskdqb(&ddquot
, &dquot
->dq_dqb
, dquot
->dq_id
);
423 /* Argh... We may need to write structure full of zeroes but that would be
424 * treated as an empty place by the rest of the code. Format change would
425 * be definitely cleaner but the problems probably are not worth it */
426 memset(&empty
, 0, sizeof(struct v2_disk_dqblk
));
427 if (!memcmp(&empty
, &ddquot
, sizeof(struct v2_disk_dqblk
)))
428 ddquot
.dqb_itime
= cpu_to_le64(1);
429 spin_unlock(&dq_data_lock
);
430 ret
= dquot
->dq_sb
->s_op
->quota_write(dquot
->dq_sb
, type
,
431 (char *)&ddquot
, sizeof(struct v2_disk_dqblk
), dquot
->dq_off
);
432 if (ret
!= sizeof(struct v2_disk_dqblk
)) {
433 printk(KERN_WARNING
"VFS: dquota write failed on dev %s\n", dquot
->dq_sb
->s_id
);
444 /* Free dquot entry in data block */
445 static int free_dqentry(struct dquot
*dquot
, uint blk
)
447 struct super_block
*sb
= dquot
->dq_sb
;
448 int type
= dquot
->dq_type
;
449 struct v2_disk_dqdbheader
*dh
;
450 dqbuf_t buf
= getdqbuf();
455 if (dquot
->dq_off
>> V2_DQBLKSIZE_BITS
!= blk
) {
456 printk(KERN_ERR
"VFS: Quota structure has offset to other "
457 "block (%u) than it should (%u).\n", blk
,
458 (uint
)(dquot
->dq_off
>> V2_DQBLKSIZE_BITS
));
461 if ((ret
= read_blk(sb
, type
, blk
, buf
)) < 0) {
462 printk(KERN_ERR
"VFS: Can't read quota data block %u\n", blk
);
465 dh
= (struct v2_disk_dqdbheader
*)buf
;
466 le16_add_cpu(&dh
->dqdh_entries
, -1);
467 if (!le16_to_cpu(dh
->dqdh_entries
)) { /* Block got free? */
468 if ((ret
= remove_free_dqentry(sb
, type
, buf
, blk
)) < 0 ||
469 (ret
= put_free_dqblk(sb
, type
, buf
, blk
)) < 0) {
470 printk(KERN_ERR
"VFS: Can't move quota data block (%u) "
471 "to free list.\n", blk
);
476 memset(buf
+(dquot
->dq_off
& ((1 << V2_DQBLKSIZE_BITS
)-1)), 0,
477 sizeof(struct v2_disk_dqblk
));
478 if (le16_to_cpu(dh
->dqdh_entries
) == V2_DQSTRINBLK
-1) {
479 /* Insert will write block itself */
480 if ((ret
= insert_free_dqentry(sb
, type
, buf
, blk
)) < 0) {
481 printk(KERN_ERR
"VFS: Can't insert quota data block (%u) to free entry list.\n", blk
);
486 if ((ret
= write_blk(sb
, type
, blk
, buf
)) < 0) {
487 printk(KERN_ERR
"VFS: Can't write quota data "
492 dquot
->dq_off
= 0; /* Quota is now unattached */
498 /* Remove reference to dquot from tree */
499 static int remove_tree(struct dquot
*dquot
, uint
*blk
, int depth
)
501 struct super_block
*sb
= dquot
->dq_sb
;
502 int type
= dquot
->dq_type
;
503 dqbuf_t buf
= getdqbuf();
506 __le32
*ref
= (__le32
*)buf
;
510 if ((ret
= read_blk(sb
, type
, *blk
, buf
)) < 0) {
511 printk(KERN_ERR
"VFS: Can't read quota data block %u\n", *blk
);
514 newblk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
515 if (depth
== V2_DQTREEDEPTH
-1) {
516 ret
= free_dqentry(dquot
, newblk
);
520 ret
= remove_tree(dquot
, &newblk
, depth
+1);
521 if (ret
>= 0 && !newblk
) {
523 ref
[GETIDINDEX(dquot
->dq_id
, depth
)] = cpu_to_le32(0);
524 for (i
= 0; i
< V2_DQBLKSIZE
&& !buf
[i
]; i
++); /* Block got empty? */
525 /* Don't put the root block into the free block list */
526 if (i
== V2_DQBLKSIZE
&& *blk
!= V2_DQTREEOFF
) {
527 put_free_dqblk(sb
, type
, buf
, *blk
);
531 if ((ret
= write_blk(sb
, type
, *blk
, buf
)) < 0)
532 printk(KERN_ERR
"VFS: Can't write quota tree "
533 "block %u.\n", *blk
);
540 /* Delete dquot from tree */
541 static int v2_delete_dquot(struct dquot
*dquot
)
543 uint tmp
= V2_DQTREEOFF
;
545 if (!dquot
->dq_off
) /* Even not allocated? */
547 return remove_tree(dquot
, &tmp
, 0);
550 /* Find entry in block */
551 static loff_t
find_block_dqentry(struct dquot
*dquot
, uint blk
)
553 dqbuf_t buf
= getdqbuf();
556 struct v2_disk_dqblk
*ddquot
= GETENTRIES(buf
);
560 if ((ret
= read_blk(dquot
->dq_sb
, dquot
->dq_type
, blk
, buf
)) < 0) {
561 printk(KERN_ERR
"VFS: Can't read quota tree block %u.\n", blk
);
565 for (i
= 0; i
< V2_DQSTRINBLK
&&
566 le32_to_cpu(ddquot
[i
].dqb_id
) != dquot
->dq_id
; i
++);
567 else { /* ID 0 as a bit more complicated searching... */
568 struct v2_disk_dqblk fakedquot
;
570 memset(&fakedquot
, 0, sizeof(struct v2_disk_dqblk
));
571 for (i
= 0; i
< V2_DQSTRINBLK
; i
++)
572 if (!le32_to_cpu(ddquot
[i
].dqb_id
) &&
573 memcmp(&fakedquot
, ddquot
+i
, sizeof(struct v2_disk_dqblk
)))
576 if (i
== V2_DQSTRINBLK
) {
577 printk(KERN_ERR
"VFS: Quota for id %u referenced "
578 "but not present.\n", dquot
->dq_id
);
583 ret
= (blk
<< V2_DQBLKSIZE_BITS
) + sizeof(struct
584 v2_disk_dqdbheader
) + i
* sizeof(struct v2_disk_dqblk
);
590 /* Find entry for given id in the tree */
591 static loff_t
find_tree_dqentry(struct dquot
*dquot
, uint blk
, int depth
)
593 dqbuf_t buf
= getdqbuf();
595 __le32
*ref
= (__le32
*)buf
;
599 if ((ret
= read_blk(dquot
->dq_sb
, dquot
->dq_type
, blk
, buf
)) < 0) {
600 printk(KERN_ERR
"VFS: Can't read quota tree block %u.\n", blk
);
604 blk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
605 if (!blk
) /* No reference? */
607 if (depth
< V2_DQTREEDEPTH
-1)
608 ret
= find_tree_dqentry(dquot
, blk
, depth
+1);
610 ret
= find_block_dqentry(dquot
, blk
);
616 /* Find entry for given id in the tree - wrapper function */
617 static inline loff_t
find_dqentry(struct dquot
*dquot
)
619 return find_tree_dqentry(dquot
, V2_DQTREEOFF
, 0);
622 static int v2_read_dquot(struct dquot
*dquot
)
624 int type
= dquot
->dq_type
;
626 struct v2_disk_dqblk ddquot
, empty
;
629 #ifdef __QUOTA_V2_PARANOIA
630 /* Invalidated quota? */
631 if (!dquot
->dq_sb
|| !sb_dqopt(dquot
->dq_sb
)->files
[type
]) {
632 printk(KERN_ERR
"VFS: Quota invalidated while reading!\n");
636 offset
= find_dqentry(dquot
);
637 if (offset
<= 0) { /* Entry not present? */
639 printk(KERN_ERR
"VFS: Can't read quota "
640 "structure for id %u.\n", dquot
->dq_id
);
642 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
643 memset(&dquot
->dq_dqb
, 0, sizeof(struct mem_dqblk
));
647 dquot
->dq_off
= offset
;
648 if ((ret
= dquot
->dq_sb
->s_op
->quota_read(dquot
->dq_sb
, type
,
649 (char *)&ddquot
, sizeof(struct v2_disk_dqblk
), offset
))
650 != sizeof(struct v2_disk_dqblk
)) {
653 printk(KERN_ERR
"VFS: Error while reading quota "
654 "structure for id %u.\n", dquot
->dq_id
);
655 memset(&ddquot
, 0, sizeof(struct v2_disk_dqblk
));
659 /* We need to escape back all-zero structure */
660 memset(&empty
, 0, sizeof(struct v2_disk_dqblk
));
661 empty
.dqb_itime
= cpu_to_le64(1);
662 if (!memcmp(&empty
, &ddquot
, sizeof(struct v2_disk_dqblk
)))
663 ddquot
.dqb_itime
= 0;
665 disk2memdqb(&dquot
->dq_dqb
, &ddquot
);
666 if (!dquot
->dq_dqb
.dqb_bhardlimit
&&
667 !dquot
->dq_dqb
.dqb_bsoftlimit
&&
668 !dquot
->dq_dqb
.dqb_ihardlimit
&&
669 !dquot
->dq_dqb
.dqb_isoftlimit
)
670 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
677 /* Check whether dquot should not be deleted. We know we are
678 * the only one operating on dquot (thanks to dq_lock) */
679 static int v2_release_dquot(struct dquot
*dquot
)
681 if (test_bit(DQ_FAKE_B
, &dquot
->dq_flags
) && !(dquot
->dq_dqb
.dqb_curinodes
| dquot
->dq_dqb
.dqb_curspace
))
682 return v2_delete_dquot(dquot
);
686 static struct quota_format_ops v2_format_ops
= {
687 .check_quota_file
= v2_check_quota_file
,
688 .read_file_info
= v2_read_file_info
,
689 .write_file_info
= v2_write_file_info
,
690 .free_file_info
= NULL
,
691 .read_dqblk
= v2_read_dquot
,
692 .commit_dqblk
= v2_write_dquot
,
693 .release_dqblk
= v2_release_dquot
,
696 static struct quota_format_type v2_quota_format
= {
697 .qf_fmt_id
= QFMT_VFS_V0
,
698 .qf_ops
= &v2_format_ops
,
699 .qf_owner
= THIS_MODULE
702 static int __init
init_v2_quota_format(void)
704 return register_quota_format(&v2_quota_format
);
707 static void __exit
exit_v2_quota_format(void)
709 unregister_quota_format(&v2_quota_format
);
712 module_init(init_v2_quota_format
);
713 module_exit(exit_v2_quota_format
);