2 * vfsv0 quota IO operations on file
5 #include <linux/errno.h>
7 #include <linux/dqblk_v2.h>
8 #include <linux/quotaio_v2.h>
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
14 #include <asm/byteorder.h>
15 #include <asm/uaccess.h>
17 #define __QUOTA_V2_PARANOIA
19 typedef char *dqbuf_t;
21 #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
22 #define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
24 /* Check whether given file is really vfsv0 quotafile */
25 static int v2_check_quota_file(struct super_block *sb, int type)
27 struct v2_disk_dqheader dqhead;
28 struct file *f = sb_dqopt(sb)->files[type];
32 static const uint quota_magics[] = V2_INITQMAGICS;
33 static const uint quota_versions[] = V2_INITQVERSIONS;
37 size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
39 if (size != sizeof(struct v2_disk_dqheader))
41 if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
42 le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
47 /* Read information header from quota file */
48 static int v2_read_file_info(struct super_block *sb, int type)
51 struct v2_disk_dqinfo dinfo;
52 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
53 struct file *f = sb_dqopt(sb)->files[type];
55 loff_t offset = V2_DQINFOOFF;
59 size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
61 if (size != sizeof(struct v2_disk_dqinfo)) {
62 printk(KERN_WARNING "Can't read info structure on device %s.\n",
63 kdevname(f->f_dentry->d_sb->s_dev));
66 info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
67 info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
68 info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
69 info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
70 info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
71 info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
75 /* Write information header to quota file */
76 static int v2_write_file_info(struct super_block *sb, int type)
79 struct v2_disk_dqinfo dinfo;
80 struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
81 struct file *f = sb_dqopt(sb)->files[type];
83 loff_t offset = V2_DQINFOOFF;
85 info->dqi_flags &= ~DQF_INFO_DIRTY;
86 dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
87 dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
88 dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
89 dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
90 dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
91 dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
94 size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
96 if (size != sizeof(struct v2_disk_dqinfo)) {
97 printk(KERN_WARNING "Can't write info structure on device %s.\n",
98 kdevname(f->f_dentry->d_sb->s_dev));
104 static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
106 m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
107 m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
108 m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
109 m->dqb_itime = le64_to_cpu(d->dqb_itime);
110 m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
111 m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
112 m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
113 m->dqb_btime = le64_to_cpu(d->dqb_btime);
116 static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
118 d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
119 d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
120 d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
121 d->dqb_itime = cpu_to_le64(m->dqb_itime);
122 d->dqb_bhardlimit = cpu_to_le32(m->dqb_bhardlimit);
123 d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
124 d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
125 d->dqb_btime = cpu_to_le64(m->dqb_btime);
126 d->dqb_id = cpu_to_le32(id);
129 static dqbuf_t getdqbuf(void)
131 dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_KERNEL);
133 printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
137 static inline void freedqbuf(dqbuf_t buf)
142 static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
146 loff_t offset = blk<<V2_DQBLKSIZE_BITS;
148 memset(buf, 0, V2_DQBLKSIZE);
151 ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
156 static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
160 loff_t offset = blk<<V2_DQBLKSIZE_BITS;
164 ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
170 /* Remove empty block from list and return it */
171 static int get_free_dqblk(struct file *filp, struct mem_dqinfo *info)
173 dqbuf_t buf = getdqbuf();
174 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
179 if (info->u.v2_i.dqi_free_blk) {
180 blk = info->u.v2_i.dqi_free_blk;
181 if ((ret = read_blk(filp, blk, buf)) < 0)
183 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
186 memset(buf, 0, V2_DQBLKSIZE);
187 if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0) /* Assure block allocation... */
189 blk = info->u.v2_i.dqi_blocks++;
191 mark_info_dirty(info);
198 /* Insert empty block to the list */
199 static int put_free_dqblk(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
201 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
204 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
205 dh->dqdh_prev_free = cpu_to_le32(0);
206 dh->dqdh_entries = cpu_to_le16(0);
207 info->u.v2_i.dqi_free_blk = blk;
208 mark_info_dirty(info);
209 if ((err = write_blk(filp, blk, buf)) < 0) /* Some strange block. We had better leave it... */
214 /* Remove given block from the list of blocks with free entries */
215 static int remove_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
217 dqbuf_t tmpbuf = getdqbuf();
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(filp, nextblk, tmpbuf)) < 0)
227 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
228 if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
232 if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
234 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
235 if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
239 info->u.v2_i.dqi_free_entry = nextblk;
240 mark_info_dirty(info);
243 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
244 if (write_blk(filp, blk, buf) < 0) /* No matter whether write succeeds block is out of list */
245 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
252 /* Insert given block to the beginning of list with free entries */
253 static int insert_free_dqentry(struct file *filp, struct mem_dqinfo *info, dqbuf_t buf, uint blk)
255 dqbuf_t tmpbuf = getdqbuf();
256 struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
261 dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
262 dh->dqdh_prev_free = cpu_to_le32(0);
263 if ((err = write_blk(filp, blk, buf)) < 0)
265 if (info->u.v2_i.dqi_free_entry) {
266 if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
268 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
269 if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
273 info->u.v2_i.dqi_free_entry = blk;
274 mark_info_dirty(info);
281 /* Find space for dquot */
282 static uint find_free_dqentry(struct dquot *dquot, int *err)
284 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
285 struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;
287 struct v2_disk_dqdbheader *dh;
288 struct v2_disk_dqblk *ddquot;
289 struct v2_disk_dqblk fakedquot;
293 if (!(buf = getdqbuf())) {
297 dh = (struct v2_disk_dqdbheader *)buf;
298 ddquot = GETENTRIES(buf);
299 if (info->u.v2_i.dqi_free_entry) {
300 blk = info->u.v2_i.dqi_free_entry;
301 if ((*err = read_blk(filp, blk, buf)) < 0)
305 blk = get_free_dqblk(filp, info);
310 memset(buf, 0, V2_DQBLKSIZE);
311 info->u.v2_i.dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */
312 mark_info_dirty(info);
314 if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */
315 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
316 printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
319 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
320 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
321 /* Find free structure in block */
322 for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
323 #ifdef __QUOTA_V2_PARANOIA
324 if (i == V2_DQSTRINBLK) {
325 printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
330 if ((*err = write_blk(filp, blk, buf)) < 0) {
331 printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
334 dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
342 /* Insert reference to structure into the trie */
343 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
345 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
346 struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
348 int ret = 0, newson = 0, newact = 0;
352 if (!(buf = getdqbuf()))
355 ret = get_free_dqblk(filp, info);
359 memset(buf, 0, V2_DQBLKSIZE);
363 if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
364 printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
369 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
372 if (depth == V2_DQTREEDEPTH-1) {
373 #ifdef __QUOTA_V2_PARANOIA
375 printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]);
380 newblk = find_free_dqentry(dquot, &ret);
383 ret = do_insert_tree(dquot, &newblk, depth+1);
384 if (newson && ret >= 0) {
385 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
386 ret = write_blk(filp, *treeblk, buf);
388 else if (newact && ret < 0)
389 put_free_dqblk(filp, info, buf, *treeblk);
395 /* Wrapper for inserting quota structure into tree */
396 static inline int dq_insert_tree(struct dquot *dquot)
398 int tmp = V2_DQTREEOFF;
399 return do_insert_tree(dquot, &tmp, 0);
403 * We don't have to be afraid of deadlocks as we never have quotas on quota files...
405 static int v2_write_dquot(struct dquot *dquot)
407 int type = dquot->dq_type;
412 struct v2_disk_dqblk ddquot;
415 if ((ret = dq_insert_tree(dquot)) < 0) {
416 printk(KERN_ERR "VFS: Error %d occured while creating quota.\n", ret);
419 filp = sb_dqopt(dquot->dq_sb)->files[type];
420 offset = dquot->dq_off;
421 mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
424 ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
426 if (ret != sizeof(struct v2_disk_dqblk)) {
427 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", kdevname(dquot->dq_dev));
437 /* Free dquot entry in data block */
438 static int free_dqentry(struct dquot *dquot, uint blk)
440 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
441 struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
442 struct v2_disk_dqdbheader *dh;
443 dqbuf_t buf = getdqbuf();
448 if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
449 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));
452 if ((ret = read_blk(filp, blk, buf)) < 0) {
453 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
456 dh = (struct v2_disk_dqdbheader *)buf;
457 dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
458 if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
459 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
460 (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
461 printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
466 memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
467 if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
468 /* Insert will write block itself */
469 if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) {
470 printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
475 if ((ret = write_blk(filp, blk, buf)) < 0) {
476 printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
480 dquot->dq_off = 0; /* Quota is now unattached */
486 /* Remove reference to dquot from tree */
487 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
489 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
490 struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;
491 dqbuf_t buf = getdqbuf();
494 u32 *ref = (u32 *)buf;
498 if ((ret = read_blk(filp, *blk, buf)) < 0) {
499 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
502 newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
503 if (depth == V2_DQTREEDEPTH-1) {
504 ret = free_dqentry(dquot, newblk);
508 ret = remove_tree(dquot, &newblk, depth+1);
509 if (ret >= 0 && !newblk) {
511 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
512 for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
513 if (i == V2_DQBLKSIZE) {
514 put_free_dqblk(filp, info, buf, *blk);
518 if ((ret = write_blk(filp, *blk, buf)) < 0)
519 printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
526 /* Delete dquot from tree */
527 static int v2_delete_dquot(struct dquot *dquot)
529 uint tmp = V2_DQTREEOFF;
531 if (!dquot->dq_off) /* Even not allocated? */
533 return remove_tree(dquot, &tmp, 0);
536 /* Find entry in block */
537 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
539 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
540 dqbuf_t buf = getdqbuf();
543 struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
547 if ((ret = read_blk(filp, blk, buf)) < 0) {
548 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
552 for (i = 0; i < V2_DQSTRINBLK && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
553 else { /* ID 0 as a bit more complicated searching... */
554 struct v2_disk_dqblk fakedquot;
556 memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
557 for (i = 0; i < V2_DQSTRINBLK; i++)
558 if (!le32_to_cpu(ddquot[i].dqb_id) && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
561 if (i == V2_DQSTRINBLK) {
562 printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
567 ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
573 /* Find entry for given id in the tree */
574 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
576 struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
577 dqbuf_t buf = getdqbuf();
579 u32 *ref = (u32 *)buf;
583 if ((ret = read_blk(filp, blk, buf)) < 0) {
584 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
588 blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
589 if (!blk) /* No reference? */
591 if (depth < V2_DQTREEDEPTH-1)
592 ret = find_tree_dqentry(dquot, blk, depth+1);
594 ret = find_block_dqentry(dquot, blk);
600 /* Find entry for given id in the tree - wrapper function */
601 static inline loff_t find_dqentry(struct dquot *dquot)
603 return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
606 static int v2_read_dquot(struct dquot *dquot)
608 int type = dquot->dq_type;
612 struct v2_disk_dqblk ddquot;
615 filp = sb_dqopt(dquot->dq_sb)->files[type];
617 #ifdef __QUOTA_V2_PARANOIA
618 if (!filp || !dquot->dq_sb) { /* Invalidated quota? */
619 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
623 offset = find_dqentry(dquot);
624 if (offset <= 0) { /* Entry not present? */
626 printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
628 dquot->dq_flags |= DQ_FAKE;
629 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
633 dquot->dq_off = offset;
636 if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
639 printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
640 memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
645 disk2memdqb(&dquot->dq_dqb, &ddquot);
651 /* Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks... */
652 static int v2_commit_dquot(struct dquot *dquot)
654 /* We clear the flag everytime so we don't loop when there was an IO error... */
655 dquot->dq_flags &= ~DQ_MOD;
656 if (dquot->dq_flags & DQ_FAKE && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
657 return v2_delete_dquot(dquot);
659 return v2_write_dquot(dquot);
662 static struct quota_format_ops v2_format_ops = {
663 check_quota_file: v2_check_quota_file,
664 read_file_info: v2_read_file_info,
665 write_file_info: v2_write_file_info,
666 free_file_info: NULL,
667 read_dqblk: v2_read_dquot,
668 commit_dqblk: v2_commit_dquot,
671 static struct quota_format_type v2_quota_format = {
672 qf_fmt_id: QFMT_VFS_V0,
673 qf_ops: &v2_format_ops,
674 qf_owner: THIS_MODULE
677 static int __init init_v2_quota_format(void)
679 return register_quota_format(&v2_quota_format);
682 static void __exit exit_v2_quota_format(void)
684 unregister_quota_format(&v2_quota_format);
689 module_init(init_v2_quota_format);
690 module_exit(exit_v2_quota_format);