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/quotaio_v2.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
15 #include <asm/byteorder.h>
16 #include <asm/uaccess.h>
18 MODULE_AUTHOR("Jan Kara");
19 MODULE_DESCRIPTION("Quota format v2 support");
20 MODULE_LICENSE("GPL");
22 #define __QUOTA_V2_PARANOIA
24 typedef char *dqbuf_t
;
26 #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
27 #define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
29 /* Check whether given file is really vfsv0 quotafile */
30 static int v2_check_quota_file(struct super_block
*sb
, int type
)
32 struct v2_disk_dqheader dqhead
;
33 struct file
*f
= sb_dqopt(sb
)->files
[type
];
37 static const uint quota_magics
[] = V2_INITQMAGICS
;
38 static const uint quota_versions
[] = V2_INITQVERSIONS
;
42 size
= f
->f_op
->read(f
, (char *)&dqhead
, sizeof(struct v2_disk_dqheader
), &offset
);
44 if (size
!= sizeof(struct v2_disk_dqheader
))
46 if (le32_to_cpu(dqhead
.dqh_magic
) != quota_magics
[type
] ||
47 le32_to_cpu(dqhead
.dqh_version
) != quota_versions
[type
])
52 /* Read information header from quota file */
53 static int v2_read_file_info(struct super_block
*sb
, int type
)
56 struct v2_disk_dqinfo dinfo
;
57 struct mem_dqinfo
*info
= sb_dqopt(sb
)->info
+type
;
58 struct file
*f
= sb_dqopt(sb
)->files
[type
];
60 loff_t offset
= V2_DQINFOOFF
;
64 size
= f
->f_op
->read(f
, (char *)&dinfo
, sizeof(struct v2_disk_dqinfo
), &offset
);
66 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
67 printk(KERN_WARNING
"Can't read info structure on device %s.\n",
68 f
->f_dentry
->d_sb
->s_id
);
71 info
->dqi_bgrace
= le32_to_cpu(dinfo
.dqi_bgrace
);
72 info
->dqi_igrace
= le32_to_cpu(dinfo
.dqi_igrace
);
73 info
->dqi_flags
= le32_to_cpu(dinfo
.dqi_flags
);
74 info
->u
.v2_i
.dqi_blocks
= le32_to_cpu(dinfo
.dqi_blocks
);
75 info
->u
.v2_i
.dqi_free_blk
= le32_to_cpu(dinfo
.dqi_free_blk
);
76 info
->u
.v2_i
.dqi_free_entry
= le32_to_cpu(dinfo
.dqi_free_entry
);
80 /* Write information header to quota file */
81 static int v2_write_file_info(struct super_block
*sb
, int type
)
84 struct v2_disk_dqinfo dinfo
;
85 struct mem_dqinfo
*info
= sb_dqopt(sb
)->info
+type
;
86 struct file
*f
= sb_dqopt(sb
)->files
[type
];
88 loff_t offset
= V2_DQINFOOFF
;
90 spin_lock(&dq_data_lock
);
91 info
->dqi_flags
&= ~DQF_INFO_DIRTY
;
92 dinfo
.dqi_bgrace
= cpu_to_le32(info
->dqi_bgrace
);
93 dinfo
.dqi_igrace
= cpu_to_le32(info
->dqi_igrace
);
94 dinfo
.dqi_flags
= cpu_to_le32(info
->dqi_flags
& DQF_MASK
);
95 spin_unlock(&dq_data_lock
);
96 dinfo
.dqi_blocks
= cpu_to_le32(info
->u
.v2_i
.dqi_blocks
);
97 dinfo
.dqi_free_blk
= cpu_to_le32(info
->u
.v2_i
.dqi_free_blk
);
98 dinfo
.dqi_free_entry
= cpu_to_le32(info
->u
.v2_i
.dqi_free_entry
);
101 size
= f
->f_op
->write(f
, (char *)&dinfo
, sizeof(struct v2_disk_dqinfo
), &offset
);
103 if (size
!= sizeof(struct v2_disk_dqinfo
)) {
104 printk(KERN_WARNING
"Can't write info structure on device %s.\n",
105 f
->f_dentry
->d_sb
->s_id
);
111 static void disk2memdqb(struct mem_dqblk
*m
, struct v2_disk_dqblk
*d
)
113 m
->dqb_ihardlimit
= le32_to_cpu(d
->dqb_ihardlimit
);
114 m
->dqb_isoftlimit
= le32_to_cpu(d
->dqb_isoftlimit
);
115 m
->dqb_curinodes
= le32_to_cpu(d
->dqb_curinodes
);
116 m
->dqb_itime
= le64_to_cpu(d
->dqb_itime
);
117 m
->dqb_bhardlimit
= le32_to_cpu(d
->dqb_bhardlimit
);
118 m
->dqb_bsoftlimit
= le32_to_cpu(d
->dqb_bsoftlimit
);
119 m
->dqb_curspace
= le64_to_cpu(d
->dqb_curspace
);
120 m
->dqb_btime
= le64_to_cpu(d
->dqb_btime
);
123 static void mem2diskdqb(struct v2_disk_dqblk
*d
, struct mem_dqblk
*m
, qid_t id
)
125 d
->dqb_ihardlimit
= cpu_to_le32(m
->dqb_ihardlimit
);
126 d
->dqb_isoftlimit
= cpu_to_le32(m
->dqb_isoftlimit
);
127 d
->dqb_curinodes
= cpu_to_le32(m
->dqb_curinodes
);
128 d
->dqb_itime
= cpu_to_le64(m
->dqb_itime
);
129 d
->dqb_bhardlimit
= cpu_to_le32(m
->dqb_bhardlimit
);
130 d
->dqb_bsoftlimit
= cpu_to_le32(m
->dqb_bsoftlimit
);
131 d
->dqb_curspace
= cpu_to_le64(m
->dqb_curspace
);
132 d
->dqb_btime
= cpu_to_le64(m
->dqb_btime
);
133 d
->dqb_id
= cpu_to_le32(id
);
136 static dqbuf_t
getdqbuf(void)
138 dqbuf_t buf
= kmalloc(V2_DQBLKSIZE
, GFP_NOFS
);
140 printk(KERN_WARNING
"VFS: Not enough memory for quota buffers.\n");
144 static inline void freedqbuf(dqbuf_t buf
)
149 static ssize_t
read_blk(struct file
*filp
, uint blk
, dqbuf_t buf
)
153 loff_t offset
= blk
<<V2_DQBLKSIZE_BITS
;
155 memset(buf
, 0, V2_DQBLKSIZE
);
158 ret
= filp
->f_op
->read(filp
, (char *)buf
, V2_DQBLKSIZE
, &offset
);
163 static ssize_t
write_blk(struct file
*filp
, uint blk
, dqbuf_t buf
)
167 loff_t offset
= blk
<<V2_DQBLKSIZE_BITS
;
171 ret
= filp
->f_op
->write(filp
, (char *)buf
, V2_DQBLKSIZE
, &offset
);
177 /* Remove empty block from list and return it */
178 static int get_free_dqblk(struct file
*filp
, int type
)
180 dqbuf_t buf
= getdqbuf();
181 struct mem_dqinfo
*info
= sb_dqinfo(filp
->f_dentry
->d_sb
, type
);
182 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
187 if (info
->u
.v2_i
.dqi_free_blk
) {
188 blk
= info
->u
.v2_i
.dqi_free_blk
;
189 if ((ret
= read_blk(filp
, blk
, buf
)) < 0)
191 info
->u
.v2_i
.dqi_free_blk
= le32_to_cpu(dh
->dqdh_next_free
);
194 memset(buf
, 0, V2_DQBLKSIZE
);
195 if ((ret
= write_blk(filp
, info
->u
.v2_i
.dqi_blocks
, buf
)) < 0) /* Assure block allocation... */
197 blk
= info
->u
.v2_i
.dqi_blocks
++;
199 mark_info_dirty(filp
->f_dentry
->d_sb
, type
);
206 /* Insert empty block to the list */
207 static int put_free_dqblk(struct file
*filp
, int type
, dqbuf_t buf
, uint blk
)
209 struct mem_dqinfo
*info
= sb_dqinfo(filp
->f_dentry
->d_sb
, type
);
210 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
213 dh
->dqdh_next_free
= cpu_to_le32(info
->u
.v2_i
.dqi_free_blk
);
214 dh
->dqdh_prev_free
= cpu_to_le32(0);
215 dh
->dqdh_entries
= cpu_to_le16(0);
216 info
->u
.v2_i
.dqi_free_blk
= blk
;
217 mark_info_dirty(filp
->f_dentry
->d_sb
, type
);
218 if ((err
= write_blk(filp
, blk
, buf
)) < 0) /* Some strange block. We had better leave it... */
223 /* Remove given block from the list of blocks with free entries */
224 static int remove_free_dqentry(struct file
*filp
, int type
, dqbuf_t buf
, uint blk
)
226 dqbuf_t tmpbuf
= getdqbuf();
227 struct mem_dqinfo
*info
= sb_dqinfo(filp
->f_dentry
->d_sb
, type
);
228 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
229 uint nextblk
= le32_to_cpu(dh
->dqdh_next_free
), prevblk
= le32_to_cpu(dh
->dqdh_prev_free
);
235 if ((err
= read_blk(filp
, nextblk
, tmpbuf
)) < 0)
237 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_prev_free
= dh
->dqdh_prev_free
;
238 if ((err
= write_blk(filp
, nextblk
, tmpbuf
)) < 0)
242 if ((err
= read_blk(filp
, prevblk
, tmpbuf
)) < 0)
244 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_next_free
= dh
->dqdh_next_free
;
245 if ((err
= write_blk(filp
, prevblk
, tmpbuf
)) < 0)
249 info
->u
.v2_i
.dqi_free_entry
= nextblk
;
250 mark_info_dirty(filp
->f_dentry
->d_sb
, type
);
253 dh
->dqdh_next_free
= dh
->dqdh_prev_free
= cpu_to_le32(0);
254 if (write_blk(filp
, blk
, buf
) < 0) /* No matter whether write succeeds block is out of list */
255 printk(KERN_ERR
"VFS: Can't write block (%u) with free entries.\n", blk
);
262 /* Insert given block to the beginning of list with free entries */
263 static int insert_free_dqentry(struct file
*filp
, int type
, dqbuf_t buf
, uint blk
)
265 dqbuf_t tmpbuf
= getdqbuf();
266 struct mem_dqinfo
*info
= sb_dqinfo(filp
->f_dentry
->d_sb
, type
);
267 struct v2_disk_dqdbheader
*dh
= (struct v2_disk_dqdbheader
*)buf
;
272 dh
->dqdh_next_free
= cpu_to_le32(info
->u
.v2_i
.dqi_free_entry
);
273 dh
->dqdh_prev_free
= cpu_to_le32(0);
274 if ((err
= write_blk(filp
, blk
, buf
)) < 0)
276 if (info
->u
.v2_i
.dqi_free_entry
) {
277 if ((err
= read_blk(filp
, info
->u
.v2_i
.dqi_free_entry
, tmpbuf
)) < 0)
279 ((struct v2_disk_dqdbheader
*)tmpbuf
)->dqdh_prev_free
= cpu_to_le32(blk
);
280 if ((err
= write_blk(filp
, info
->u
.v2_i
.dqi_free_entry
, tmpbuf
)) < 0)
284 info
->u
.v2_i
.dqi_free_entry
= blk
;
285 mark_info_dirty(filp
->f_dentry
->d_sb
, type
);
292 /* Find space for dquot */
293 static uint
find_free_dqentry(struct dquot
*dquot
, int *err
)
295 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
296 struct mem_dqinfo
*info
= sb_dqopt(dquot
->dq_sb
)->info
+dquot
->dq_type
;
298 struct v2_disk_dqdbheader
*dh
;
299 struct v2_disk_dqblk
*ddquot
;
300 struct v2_disk_dqblk fakedquot
;
304 if (!(buf
= getdqbuf())) {
308 dh
= (struct v2_disk_dqdbheader
*)buf
;
309 ddquot
= GETENTRIES(buf
);
310 if (info
->u
.v2_i
.dqi_free_entry
) {
311 blk
= info
->u
.v2_i
.dqi_free_entry
;
312 if ((*err
= read_blk(filp
, blk
, buf
)) < 0)
316 blk
= get_free_dqblk(filp
, dquot
->dq_type
);
322 memset(buf
, 0, V2_DQBLKSIZE
);
323 info
->u
.v2_i
.dqi_free_entry
= blk
; /* This is enough as block is already zeroed and entry list is empty... */
324 mark_info_dirty(dquot
->dq_sb
, dquot
->dq_type
);
326 if (le16_to_cpu(dh
->dqdh_entries
)+1 >= V2_DQSTRINBLK
) /* Block will be full? */
327 if ((*err
= remove_free_dqentry(filp
, dquot
->dq_type
, buf
, blk
)) < 0) {
328 printk(KERN_ERR
"VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk
);
331 dh
->dqdh_entries
= cpu_to_le16(le16_to_cpu(dh
->dqdh_entries
)+1);
332 memset(&fakedquot
, 0, sizeof(struct v2_disk_dqblk
));
333 /* Find free structure in block */
334 for (i
= 0; i
< V2_DQSTRINBLK
&& memcmp(&fakedquot
, ddquot
+i
, sizeof(struct v2_disk_dqblk
)); i
++);
335 #ifdef __QUOTA_V2_PARANOIA
336 if (i
== V2_DQSTRINBLK
) {
337 printk(KERN_ERR
"VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
342 if ((*err
= write_blk(filp
, blk
, buf
)) < 0) {
343 printk(KERN_ERR
"VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk
);
346 dquot
->dq_off
= (blk
<<V2_DQBLKSIZE_BITS
)+sizeof(struct v2_disk_dqdbheader
)+i
*sizeof(struct v2_disk_dqblk
);
354 /* Insert reference to structure into the trie */
355 static int do_insert_tree(struct dquot
*dquot
, uint
*treeblk
, int depth
)
357 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
359 int ret
= 0, newson
= 0, newact
= 0;
363 if (!(buf
= getdqbuf()))
366 ret
= get_free_dqblk(filp
, dquot
->dq_type
);
370 memset(buf
, 0, V2_DQBLKSIZE
);
374 if ((ret
= read_blk(filp
, *treeblk
, buf
)) < 0) {
375 printk(KERN_ERR
"VFS: Can't read tree quota block %u.\n", *treeblk
);
380 newblk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
383 if (depth
== V2_DQTREEDEPTH
-1) {
384 #ifdef __QUOTA_V2_PARANOIA
386 printk(KERN_ERR
"VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]));
391 newblk
= find_free_dqentry(dquot
, &ret
);
394 ret
= do_insert_tree(dquot
, &newblk
, depth
+1);
395 if (newson
&& ret
>= 0) {
396 ref
[GETIDINDEX(dquot
->dq_id
, depth
)] = cpu_to_le32(newblk
);
397 ret
= write_blk(filp
, *treeblk
, buf
);
399 else if (newact
&& ret
< 0)
400 put_free_dqblk(filp
, dquot
->dq_type
, buf
, *treeblk
);
406 /* Wrapper for inserting quota structure into tree */
407 static inline int dq_insert_tree(struct dquot
*dquot
)
409 int tmp
= V2_DQTREEOFF
;
410 return do_insert_tree(dquot
, &tmp
, 0);
414 * We don't have to be afraid of deadlocks as we never have quotas on quota files...
416 static int v2_write_dquot(struct dquot
*dquot
)
418 int type
= dquot
->dq_type
;
423 struct v2_disk_dqblk ddquot
, empty
;
425 /* dq_off is guarded by dqio_sem */
427 if ((ret
= dq_insert_tree(dquot
)) < 0) {
428 printk(KERN_ERR
"VFS: Error %Zd occurred while creating quota.\n", ret
);
431 filp
= sb_dqopt(dquot
->dq_sb
)->files
[type
];
432 offset
= dquot
->dq_off
;
433 spin_lock(&dq_data_lock
);
434 mem2diskdqb(&ddquot
, &dquot
->dq_dqb
, dquot
->dq_id
);
435 /* Argh... We may need to write structure full of zeroes but that would be
436 * treated as an empty place by the rest of the code. Format change would
437 * be definitely cleaner but the problems probably are not worth it */
438 memset(&empty
, 0, sizeof(struct v2_disk_dqblk
));
439 if (!memcmp(&empty
, &ddquot
, sizeof(struct v2_disk_dqblk
)))
440 ddquot
.dqb_itime
= cpu_to_le64(1);
441 spin_unlock(&dq_data_lock
);
444 ret
= filp
->f_op
->write(filp
, (char *)&ddquot
, sizeof(struct v2_disk_dqblk
), &offset
);
446 if (ret
!= sizeof(struct v2_disk_dqblk
)) {
447 printk(KERN_WARNING
"VFS: dquota write failed on dev %s\n", dquot
->dq_sb
->s_id
);
458 /* Free dquot entry in data block */
459 static int free_dqentry(struct dquot
*dquot
, uint blk
)
461 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
462 struct v2_disk_dqdbheader
*dh
;
463 dqbuf_t buf
= getdqbuf();
468 if (dquot
->dq_off
>> V2_DQBLKSIZE_BITS
!= blk
) {
469 printk(KERN_ERR
"VFS: Quota structure has offset to other block (%u) than it should (%u).\n", blk
, (uint
)(dquot
->dq_off
>> V2_DQBLKSIZE_BITS
));
472 if ((ret
= read_blk(filp
, blk
, buf
)) < 0) {
473 printk(KERN_ERR
"VFS: Can't read quota data block %u\n", blk
);
476 dh
= (struct v2_disk_dqdbheader
*)buf
;
477 dh
->dqdh_entries
= cpu_to_le16(le16_to_cpu(dh
->dqdh_entries
)-1);
478 if (!le16_to_cpu(dh
->dqdh_entries
)) { /* Block got free? */
479 if ((ret
= remove_free_dqentry(filp
, dquot
->dq_type
, buf
, blk
)) < 0 ||
480 (ret
= put_free_dqblk(filp
, dquot
->dq_type
, buf
, blk
)) < 0) {
481 printk(KERN_ERR
"VFS: Can't move quota data block (%u) to free list.\n", blk
);
486 memset(buf
+(dquot
->dq_off
& ((1 << V2_DQBLKSIZE_BITS
)-1)), 0, sizeof(struct v2_disk_dqblk
));
487 if (le16_to_cpu(dh
->dqdh_entries
) == V2_DQSTRINBLK
-1) {
488 /* Insert will write block itself */
489 if ((ret
= insert_free_dqentry(filp
, dquot
->dq_type
, buf
, blk
)) < 0) {
490 printk(KERN_ERR
"VFS: Can't insert quota data block (%u) to free entry list.\n", blk
);
495 if ((ret
= write_blk(filp
, blk
, buf
)) < 0) {
496 printk(KERN_ERR
"VFS: Can't write quota data block %u\n", blk
);
500 dquot
->dq_off
= 0; /* Quota is now unattached */
506 /* Remove reference to dquot from tree */
507 static int remove_tree(struct dquot
*dquot
, uint
*blk
, int depth
)
509 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
510 dqbuf_t buf
= getdqbuf();
513 __le32
*ref
= (__le32
*)buf
;
517 if ((ret
= read_blk(filp
, *blk
, buf
)) < 0) {
518 printk(KERN_ERR
"VFS: Can't read quota data block %u\n", *blk
);
521 newblk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
522 if (depth
== V2_DQTREEDEPTH
-1) {
523 ret
= free_dqentry(dquot
, newblk
);
527 ret
= remove_tree(dquot
, &newblk
, depth
+1);
528 if (ret
>= 0 && !newblk
) {
530 ref
[GETIDINDEX(dquot
->dq_id
, depth
)] = cpu_to_le32(0);
531 for (i
= 0; i
< V2_DQBLKSIZE
&& !buf
[i
]; i
++); /* Block got empty? */
532 if (i
== V2_DQBLKSIZE
) {
533 put_free_dqblk(filp
, dquot
->dq_type
, buf
, *blk
);
537 if ((ret
= write_blk(filp
, *blk
, buf
)) < 0)
538 printk(KERN_ERR
"VFS: Can't write quota tree block %u.\n", *blk
);
545 /* Delete dquot from tree */
546 static int v2_delete_dquot(struct dquot
*dquot
)
548 uint tmp
= V2_DQTREEOFF
;
550 if (!dquot
->dq_off
) /* Even not allocated? */
552 return remove_tree(dquot
, &tmp
, 0);
555 /* Find entry in block */
556 static loff_t
find_block_dqentry(struct dquot
*dquot
, uint blk
)
558 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
559 dqbuf_t buf
= getdqbuf();
562 struct v2_disk_dqblk
*ddquot
= GETENTRIES(buf
);
566 if ((ret
= read_blk(filp
, blk
, buf
)) < 0) {
567 printk(KERN_ERR
"VFS: Can't read quota tree block %u.\n", blk
);
571 for (i
= 0; i
< V2_DQSTRINBLK
&& le32_to_cpu(ddquot
[i
].dqb_id
) != dquot
->dq_id
; i
++);
572 else { /* ID 0 as a bit more complicated searching... */
573 struct v2_disk_dqblk fakedquot
;
575 memset(&fakedquot
, 0, sizeof(struct v2_disk_dqblk
));
576 for (i
= 0; i
< V2_DQSTRINBLK
; i
++)
577 if (!le32_to_cpu(ddquot
[i
].dqb_id
) && memcmp(&fakedquot
, ddquot
+i
, sizeof(struct v2_disk_dqblk
)))
580 if (i
== V2_DQSTRINBLK
) {
581 printk(KERN_ERR
"VFS: Quota for id %u referenced but not present.\n", dquot
->dq_id
);
586 ret
= (blk
<< V2_DQBLKSIZE_BITS
) + sizeof(struct v2_disk_dqdbheader
) + i
* sizeof(struct v2_disk_dqblk
);
592 /* Find entry for given id in the tree */
593 static loff_t
find_tree_dqentry(struct dquot
*dquot
, uint blk
, int depth
)
595 struct file
*filp
= sb_dqopt(dquot
->dq_sb
)->files
[dquot
->dq_type
];
596 dqbuf_t buf
= getdqbuf();
598 __le32
*ref
= (__le32
*)buf
;
602 if ((ret
= read_blk(filp
, blk
, buf
)) < 0) {
603 printk(KERN_ERR
"VFS: Can't read quota tree block %u.\n", blk
);
607 blk
= le32_to_cpu(ref
[GETIDINDEX(dquot
->dq_id
, depth
)]);
608 if (!blk
) /* No reference? */
610 if (depth
< V2_DQTREEDEPTH
-1)
611 ret
= find_tree_dqentry(dquot
, blk
, depth
+1);
613 ret
= find_block_dqentry(dquot
, blk
);
619 /* Find entry for given id in the tree - wrapper function */
620 static inline loff_t
find_dqentry(struct dquot
*dquot
)
622 return find_tree_dqentry(dquot
, V2_DQTREEOFF
, 0);
625 static int v2_read_dquot(struct dquot
*dquot
)
627 int type
= dquot
->dq_type
;
631 struct v2_disk_dqblk ddquot
, empty
;
634 filp
= sb_dqopt(dquot
->dq_sb
)->files
[type
];
636 #ifdef __QUOTA_V2_PARANOIA
637 if (!filp
|| !dquot
->dq_sb
) { /* Invalidated quota? */
638 printk(KERN_ERR
"VFS: Quota invalidated while reading!\n");
642 offset
= find_dqentry(dquot
);
643 if (offset
<= 0) { /* Entry not present? */
645 printk(KERN_ERR
"VFS: Can't read quota structure for id %u.\n", dquot
->dq_id
);
647 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
648 memset(&dquot
->dq_dqb
, 0, sizeof(struct mem_dqblk
));
652 dquot
->dq_off
= offset
;
655 if ((ret
= filp
->f_op
->read(filp
, (char *)&ddquot
, sizeof(struct v2_disk_dqblk
), &offset
)) != sizeof(struct v2_disk_dqblk
)) {
658 printk(KERN_ERR
"VFS: Error while reading quota structure for id %u.\n", dquot
->dq_id
);
659 memset(&ddquot
, 0, sizeof(struct v2_disk_dqblk
));
663 /* We need to escape back all-zero structure */
664 memset(&empty
, 0, sizeof(struct v2_disk_dqblk
));
665 empty
.dqb_itime
= cpu_to_le64(1);
666 if (!memcmp(&empty
, &ddquot
, sizeof(struct v2_disk_dqblk
)))
667 ddquot
.dqb_itime
= 0;
670 disk2memdqb(&dquot
->dq_dqb
, &ddquot
);
671 if (!dquot
->dq_dqb
.dqb_bhardlimit
&&
672 !dquot
->dq_dqb
.dqb_bsoftlimit
&&
673 !dquot
->dq_dqb
.dqb_ihardlimit
&&
674 !dquot
->dq_dqb
.dqb_isoftlimit
)
675 set_bit(DQ_FAKE_B
, &dquot
->dq_flags
);
682 /* Check whether dquot should not be deleted. We know we are
683 * the only one operating on dquot (thanks to dq_lock) */
684 static int v2_release_dquot(struct dquot
*dquot
)
686 if (test_bit(DQ_FAKE_B
, &dquot
->dq_flags
) && !(dquot
->dq_dqb
.dqb_curinodes
| dquot
->dq_dqb
.dqb_curspace
))
687 return v2_delete_dquot(dquot
);
691 static struct quota_format_ops v2_format_ops
= {
692 .check_quota_file
= v2_check_quota_file
,
693 .read_file_info
= v2_read_file_info
,
694 .write_file_info
= v2_write_file_info
,
695 .free_file_info
= NULL
,
696 .read_dqblk
= v2_read_dquot
,
697 .commit_dqblk
= v2_write_dquot
,
698 .release_dqblk
= v2_release_dquot
,
701 static struct quota_format_type v2_quota_format
= {
702 .qf_fmt_id
= QFMT_VFS_V0
,
703 .qf_ops
= &v2_format_ops
,
704 .qf_owner
= THIS_MODULE
707 static int __init
init_v2_quota_format(void)
709 return register_quota_format(&v2_quota_format
);
712 static void __exit
exit_v2_quota_format(void)
714 unregister_quota_format(&v2_quota_format
);
717 module_init(init_v2_quota_format
);
718 module_exit(exit_v2_quota_format
);