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>
14 #include <linux/quotaops.h>
16 #include <asm/byteorder.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 #define QUOTABLOCK_BITS 10
30 #define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
32 static inline qsize_t v2_stoqb(qsize_t space)
34 return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
37 static inline qsize_t v2_qbtos(qsize_t blocks)
39 return blocks << QUOTABLOCK_BITS;
42 /* Check whether given file is really vfsv0 quotafile */
43 static int v2_check_quota_file(struct super_block *sb, int type)
45 struct v2_disk_dqheader dqhead;
47 static const uint quota_magics[] = V2_INITQMAGICS;
48 static const uint quota_versions[] = V2_INITQVERSIONS;
50 size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
51 if (size != sizeof(struct v2_disk_dqheader)) {
52 printk("quota_v2: failed read expected=%zd got=%zd\n",
53 sizeof(struct v2_disk_dqheader), size);
56 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
57 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
62 /* Read information header from quota file */
63 static int v2_read_file_info(struct super_block *sb, int type)
65 struct v2_disk_dqinfo dinfo;
66 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
69 size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
70 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
71 if (size != sizeof(struct v2_disk_dqinfo)) {
72 printk(KERN_WARNING "Can't read info structure on device %s.\n",
76 /* limits are stored as unsigned 32-bit data */
77 info->dqi_maxblimit = 0xffffffff;
78 info->dqi_maxilimit = 0xffffffff;
79 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
80 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
81 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
82 info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
83 info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
84 info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
88 /* Write information header to quota file */
89 static int v2_write_file_info(struct super_block *sb, int type)
91 struct v2_disk_dqinfo dinfo;
92 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
95 spin_lock(&dq_data_lock);
96 info->dqi_flags &= ~DQF_INFO_DIRTY;
97 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
98 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
99 dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
100 spin_unlock(&dq_data_lock);
101 dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
102 dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
103 dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
104 size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
105 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
106 if (size != sizeof(struct v2_disk_dqinfo)) {
107 printk(KERN_WARNING "Can't write info structure on device %s.\n",
114 static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
116 m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
117 m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
118 m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
119 m->dqb_itime = le64_to_cpu(d->dqb_itime);
120 m->dqb_bhardlimit = v2_qbtos(le32_to_cpu(d->dqb_bhardlimit));
121 m->dqb_bsoftlimit = v2_qbtos(le32_to_cpu(d->dqb_bsoftlimit));
122 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
123 m->dqb_btime = le64_to_cpu(d->dqb_btime);
126 static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
128 d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
129 d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
130 d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
131 d->dqb_itime = cpu_to_le64(m->dqb_itime);
132 d->dqb_bhardlimit = cpu_to_le32(v2_qbtos(m->dqb_bhardlimit));
133 d->dqb_bsoftlimit = cpu_to_le32(v2_qbtos(m->dqb_bsoftlimit));
134 d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
135 d->dqb_btime = cpu_to_le64(m->dqb_btime);
136 d->dqb_id = cpu_to_le32(id);
139 static dqbuf_t getdqbuf(void)
141 dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_NOFS);
143 printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
147 static inline void freedqbuf(dqbuf_t buf)
152 static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
154 memset(buf, 0, V2_DQBLKSIZE);
155 return sb->s_op->quota_read(sb, type, (char *)buf,
156 V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
159 static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
161 return sb->s_op->quota_write(sb, type, (char *)buf,
162 V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
165 /* Remove empty block from list and return it */
166 static int get_free_dqblk(struct super_block *sb, int type)
168 dqbuf_t buf = getdqbuf();
169 struct mem_dqinfo *info = sb_dqinfo(sb, type);
170 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
175 if (info->u.v2_i.dqi_free_blk) {
176 blk = info->u.v2_i.dqi_free_blk;
177 if ((ret = read_blk(sb, type, blk, buf)) < 0)
179 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
182 memset(buf, 0, V2_DQBLKSIZE);
183 /* Assure block allocation... */
184 if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
186 blk = info->u.v2_i.dqi_blocks++;
188 mark_info_dirty(sb, type);
195 /* Insert empty block to the list */
196 static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
198 struct mem_dqinfo *info = sb_dqinfo(sb, type);
199 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
202 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
203 dh->dqdh_prev_free = cpu_to_le32(0);
204 dh->dqdh_entries = cpu_to_le16(0);
205 info->u.v2_i.dqi_free_blk = blk;
206 mark_info_dirty(sb, type);
207 /* Some strange block. We had better leave it... */
208 if ((err = write_blk(sb, type, blk, buf)) < 0)
213 /* Remove given block from the list of blocks with free entries */
214 static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
216 dqbuf_t tmpbuf = getdqbuf();
217 struct mem_dqinfo *info = sb_dqinfo(sb, type);
218 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
219 uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
225 if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
227 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
228 if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
232 if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
234 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
235 if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
239 info->u.v2_i.dqi_free_entry = nextblk;
240 mark_info_dirty(sb, type);
243 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
244 /* No matter whether write succeeds block is out of list */
245 if (write_blk(sb, type, blk, buf) < 0)
246 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
253 /* Insert given block to the beginning of list with free entries */
254 static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
256 dqbuf_t tmpbuf = getdqbuf();
257 struct mem_dqinfo *info = sb_dqinfo(sb, type);
258 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
263 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
264 dh->dqdh_prev_free = cpu_to_le32(0);
265 if ((err = write_blk(sb, type, blk, buf)) < 0)
267 if (info->u.v2_i.dqi_free_entry) {
268 if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
270 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
271 if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
275 info->u.v2_i.dqi_free_entry = blk;
276 mark_info_dirty(sb, type);
283 /* Find space for dquot */
284 static uint find_free_dqentry(struct dquot *dquot, int *err)
286 struct super_block *sb = dquot->dq_sb;
287 struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
289 struct v2_disk_dqdbheader *dh;
290 struct v2_disk_dqblk *ddquot;
291 struct v2_disk_dqblk fakedquot;
295 if (!(buf = getdqbuf())) {
299 dh = (struct v2_disk_dqdbheader *)buf;
300 ddquot = GETENTRIES(buf);
301 if (info->u.v2_i.dqi_free_entry) {
302 blk = info->u.v2_i.dqi_free_entry;
303 if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
307 blk = get_free_dqblk(sb, dquot->dq_type);
313 memset(buf, 0, V2_DQBLKSIZE);
314 /* This is enough as block is already zeroed and entry list is empty... */
315 info->u.v2_i.dqi_free_entry = blk;
316 mark_info_dirty(sb, dquot->dq_type);
318 if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */
319 if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
320 printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
323 le16_add_cpu(&dh->dqdh_entries, 1);
324 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
325 /* Find free structure in block */
326 for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
327 #ifdef __QUOTA_V2_PARANOIA
328 if (i == V2_DQSTRINBLK) {
329 printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
334 if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
335 printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
338 dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
346 /* Insert reference to structure into the trie */
347 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
349 struct super_block *sb = dquot->dq_sb;
351 int ret = 0, newson = 0, newact = 0;
355 if (!(buf = getdqbuf()))
358 ret = get_free_dqblk(sb, dquot->dq_type);
362 memset(buf, 0, V2_DQBLKSIZE);
366 if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
367 printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
372 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
375 if (depth == V2_DQTREEDEPTH-1) {
376 #ifdef __QUOTA_V2_PARANOIA
378 printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
383 newblk = find_free_dqentry(dquot, &ret);
386 ret = do_insert_tree(dquot, &newblk, depth+1);
387 if (newson && ret >= 0) {
388 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
389 ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
391 else if (newact && ret < 0)
392 put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
398 /* Wrapper for inserting quota structure into tree */
399 static inline int dq_insert_tree(struct dquot *dquot)
401 int tmp = V2_DQTREEOFF;
402 return do_insert_tree(dquot, &tmp, 0);
406 * We don't have to be afraid of deadlocks as we never have quotas on quota files...
408 static int v2_write_dquot(struct dquot *dquot)
410 int type = dquot->dq_type;
412 struct v2_disk_dqblk ddquot, empty;
414 /* dq_off is guarded by dqio_mutex */
416 if ((ret = dq_insert_tree(dquot)) < 0) {
417 printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
420 spin_lock(&dq_data_lock);
421 mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
422 /* Argh... We may need to write structure full of zeroes but that would be
423 * treated as an empty place by the rest of the code. Format change would
424 * be definitely cleaner but the problems probably are not worth it */
425 memset(&empty, 0, sizeof(struct v2_disk_dqblk));
426 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
427 ddquot.dqb_itime = cpu_to_le64(1);
428 spin_unlock(&dq_data_lock);
429 ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
430 (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
431 if (ret != sizeof(struct v2_disk_dqblk)) {
432 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
443 /* Free dquot entry in data block */
444 static int free_dqentry(struct dquot *dquot, uint blk)
446 struct super_block *sb = dquot->dq_sb;
447 int type = dquot->dq_type;
448 struct v2_disk_dqdbheader *dh;
449 dqbuf_t buf = getdqbuf();
454 if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
455 printk(KERN_ERR "VFS: Quota structure has offset to other "
456 "block (%u) than it should (%u).\n", blk,
457 (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
460 if ((ret = read_blk(sb, type, blk, buf)) < 0) {
461 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
464 dh = (struct v2_disk_dqdbheader *)buf;
465 le16_add_cpu(&dh->dqdh_entries, -1);
466 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
467 if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
468 (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
469 printk(KERN_ERR "VFS: Can't move quota data block (%u) "
470 "to free list.\n", blk);
475 memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
476 sizeof(struct v2_disk_dqblk));
477 if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
478 /* Insert will write block itself */
479 if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
480 printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
485 if ((ret = write_blk(sb, type, blk, buf)) < 0) {
486 printk(KERN_ERR "VFS: Can't write quota data "
491 dquot->dq_off = 0; /* Quota is now unattached */
497 /* Remove reference to dquot from tree */
498 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
500 struct super_block *sb = dquot->dq_sb;
501 int type = dquot->dq_type;
502 dqbuf_t buf = getdqbuf();
505 __le32 *ref = (__le32 *)buf;
509 if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
510 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
513 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
514 if (depth == V2_DQTREEDEPTH-1) {
515 ret = free_dqentry(dquot, newblk);
519 ret = remove_tree(dquot, &newblk, depth+1);
520 if (ret >= 0 && !newblk) {
522 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
523 for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
524 /* Don't put the root block into the free block list */
525 if (i == V2_DQBLKSIZE && *blk != V2_DQTREEOFF) {
526 put_free_dqblk(sb, type, buf, *blk);
530 if ((ret = write_blk(sb, type, *blk, buf)) < 0)
531 printk(KERN_ERR "VFS: Can't write quota tree "
532 "block %u.\n", *blk);
539 /* Delete dquot from tree */
540 static int v2_delete_dquot(struct dquot *dquot)
542 uint tmp = V2_DQTREEOFF;
544 if (!dquot->dq_off) /* Even not allocated? */
546 return remove_tree(dquot, &tmp, 0);
549 /* Find entry in block */
550 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
552 dqbuf_t buf = getdqbuf();
555 struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
559 if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
560 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
564 for (i = 0; i < V2_DQSTRINBLK &&
565 le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
566 else { /* ID 0 as a bit more complicated searching... */
567 struct v2_disk_dqblk fakedquot;
569 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
570 for (i = 0; i < V2_DQSTRINBLK; i++)
571 if (!le32_to_cpu(ddquot[i].dqb_id) &&
572 memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
575 if (i == V2_DQSTRINBLK) {
576 printk(KERN_ERR "VFS: Quota for id %u referenced "
577 "but not present.\n", dquot->dq_id);
582 ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
583 v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
589 /* Find entry for given id in the tree */
590 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
592 dqbuf_t buf = getdqbuf();
594 __le32 *ref = (__le32 *)buf;
598 if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
599 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
603 blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
604 if (!blk) /* No reference? */
606 if (depth < V2_DQTREEDEPTH-1)
607 ret = find_tree_dqentry(dquot, blk, depth+1);
609 ret = find_block_dqentry(dquot, blk);
615 /* Find entry for given id in the tree - wrapper function */
616 static inline loff_t find_dqentry(struct dquot *dquot)
618 return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
621 static int v2_read_dquot(struct dquot *dquot)
623 int type = dquot->dq_type;
625 struct v2_disk_dqblk ddquot, empty;
628 #ifdef __QUOTA_V2_PARANOIA
629 /* Invalidated quota? */
630 if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
631 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
635 offset = find_dqentry(dquot);
636 if (offset <= 0) { /* Entry not present? */
638 printk(KERN_ERR "VFS: Can't read quota "
639 "structure for id %u.\n", dquot->dq_id);
641 set_bit(DQ_FAKE_B, &dquot->dq_flags);
642 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
646 dquot->dq_off = offset;
647 if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
648 (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
649 != sizeof(struct v2_disk_dqblk)) {
652 printk(KERN_ERR "VFS: Error while reading quota "
653 "structure for id %u.\n", dquot->dq_id);
654 memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
658 /* We need to escape back all-zero structure */
659 memset(&empty, 0, sizeof(struct v2_disk_dqblk));
660 empty.dqb_itime = cpu_to_le64(1);
661 if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
662 ddquot.dqb_itime = 0;
664 disk2memdqb(&dquot->dq_dqb, &ddquot);
665 if (!dquot->dq_dqb.dqb_bhardlimit &&
666 !dquot->dq_dqb.dqb_bsoftlimit &&
667 !dquot->dq_dqb.dqb_ihardlimit &&
668 !dquot->dq_dqb.dqb_isoftlimit)
669 set_bit(DQ_FAKE_B, &dquot->dq_flags);
676 /* Check whether dquot should not be deleted. We know we are
677 * the only one operating on dquot (thanks to dq_lock) */
678 static int v2_release_dquot(struct dquot *dquot)
680 if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
681 return v2_delete_dquot(dquot);
685 static struct quota_format_ops v2_format_ops = {
686 .check_quota_file = v2_check_quota_file,
687 .read_file_info = v2_read_file_info,
688 .write_file_info = v2_write_file_info,
689 .free_file_info = NULL,
690 .read_dqblk = v2_read_dquot,
691 .commit_dqblk = v2_write_dquot,
692 .release_dqblk = v2_release_dquot,
695 static struct quota_format_type v2_quota_format = {
696 .qf_fmt_id = QFMT_VFS_V0,
697 .qf_ops = &v2_format_ops,
698 .qf_owner = THIS_MODULE
701 static int __init init_v2_quota_format(void)
703 return register_quota_format(&v2_quota_format);
706 static void __exit exit_v2_quota_format(void)
708 unregister_quota_format(&v2_quota_format);
711 module_init(init_v2_quota_format);
712 module_exit(exit_v2_quota_format);