OSDN Git Service

[NETFILTER]: Fix deadlock with ip_queue/ip6_queue
[linux-kernel-docs/linux-2.4.36.git] / fs / quota_v2.c
1 /*
2  *      vfsv0 quota IO operations on file
3  */
4
5 #include <linux/errno.h>
6 #include <linux/fs.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>
13
14 #include <asm/byteorder.h>
15 #include <asm/uaccess.h>
16
17 #define __QUOTA_V2_PARANOIA
18
19 typedef char *dqbuf_t;
20
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)))
23
24 /* Check whether given file is really vfsv0 quotafile */
25 static int v2_check_quota_file(struct super_block *sb, int type)
26 {
27         struct v2_disk_dqheader dqhead;
28         struct file *f = sb_dqopt(sb)->files[type];
29         mm_segment_t fs;
30         ssize_t size;
31         loff_t offset = 0;
32         static const uint quota_magics[] = V2_INITQMAGICS;
33         static const uint quota_versions[] = V2_INITQVERSIONS;
34  
35         fs = get_fs();
36         set_fs(KERNEL_DS);
37         size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
38         set_fs(fs);
39         if (size != sizeof(struct v2_disk_dqheader))
40                 return 0;
41         if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
42             le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
43                 return 0;
44         return 1;
45 }
46
47 /* Read information header from quota file */
48 static int v2_read_file_info(struct super_block *sb, int type)
49 {
50         mm_segment_t fs;
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];
54         ssize_t size;
55         loff_t offset = V2_DQINFOOFF;
56
57         fs = get_fs();
58         set_fs(KERNEL_DS);
59         size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
60         set_fs(fs);
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));
64                 return -1;
65         }
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);
72         return 0;
73 }
74
75 /* Write information header to quota file */
76 static int v2_write_file_info(struct super_block *sb, int type)
77 {
78         mm_segment_t fs;
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];
82         ssize_t size;
83         loff_t offset = V2_DQINFOOFF;
84
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);
92         fs = get_fs();
93         set_fs(KERNEL_DS);
94         size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
95         set_fs(fs);
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));
99                 return -1;
100         }
101         return 0;
102 }
103
104 static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
105 {
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);
114 }
115
116 static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
117 {
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);
127 }
128
129 static dqbuf_t getdqbuf(void)
130 {
131         dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_KERNEL);
132         if (!buf)
133                 printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
134         return buf;
135 }
136
137 static inline void freedqbuf(dqbuf_t buf)
138 {
139         kfree(buf);
140 }
141
142 static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
143 {
144         mm_segment_t fs;
145         ssize_t ret;
146         loff_t offset = blk<<V2_DQBLKSIZE_BITS;
147
148         memset(buf, 0, V2_DQBLKSIZE);
149         fs = get_fs();
150         set_fs(KERNEL_DS);
151         ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
152         set_fs(fs);
153         return ret;
154 }
155
156 static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
157 {
158         mm_segment_t fs;
159         ssize_t ret;
160         loff_t offset = blk<<V2_DQBLKSIZE_BITS;
161
162         fs = get_fs();
163         set_fs(KERNEL_DS);
164         ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
165         set_fs(fs);
166         return ret;
167
168 }
169
170 /* Remove empty block from list and return it */
171 static int get_free_dqblk(struct file *filp, struct mem_dqinfo *info)
172 {
173         dqbuf_t buf = getdqbuf();
174         struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
175         int ret, blk;
176
177         if (!buf)
178                 return -ENOMEM;
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)
182                         goto out_buf;
183                 info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
184         }
185         else {
186                 memset(buf, 0, V2_DQBLKSIZE);
187                 if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0)  /* Assure block allocation... */
188                         goto out_buf;
189                 blk = info->u.v2_i.dqi_blocks++;
190         }
191         mark_info_dirty(info);
192         ret = blk;
193 out_buf:
194         freedqbuf(buf);
195         return ret;
196 }
197
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)
200 {
201         struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
202         int err;
203
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... */
210                 return err;
211         return 0;
212 }
213
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)
216 {
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);
220         int err;
221
222         if (!tmpbuf)
223                 return -ENOMEM;
224         if (nextblk) {
225                 if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
226                         goto out_buf;
227                 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
228                 if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
229                         goto out_buf;
230         }
231         if (prevblk) {
232                 if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
233                         goto out_buf;
234                 ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
235                 if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
236                         goto out_buf;
237         }
238         else {
239                 info->u.v2_i.dqi_free_entry = nextblk;
240                 mark_info_dirty(info);
241         }
242         freedqbuf(tmpbuf);
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);
246         return 0;
247 out_buf:
248         freedqbuf(tmpbuf);
249         return err;
250 }
251
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)
254 {
255         dqbuf_t tmpbuf = getdqbuf();
256         struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
257         int err;
258
259         if (!tmpbuf)
260                 return -ENOMEM;
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)
264                 goto out_buf;
265         if (info->u.v2_i.dqi_free_entry) {
266                 if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
267                         goto out_buf;
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)
270                         goto out_buf;
271         }
272         freedqbuf(tmpbuf);
273         info->u.v2_i.dqi_free_entry = blk;
274         mark_info_dirty(info);
275         return 0;
276 out_buf:
277         freedqbuf(tmpbuf);
278         return err;
279 }
280
281 /* Find space for dquot */
282 static uint find_free_dqentry(struct dquot *dquot, int *err)
283 {
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;
286         uint blk, i;
287         struct v2_disk_dqdbheader *dh;
288         struct v2_disk_dqblk *ddquot;
289         struct v2_disk_dqblk fakedquot;
290         dqbuf_t buf;
291
292         *err = 0;
293         if (!(buf = getdqbuf())) {
294                 *err = -ENOMEM;
295                 return 0;
296         }
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)
302                         goto out_buf;
303         }
304         else {
305                 blk = get_free_dqblk(filp, info);
306                 if ((int)blk < 0) {
307                         *err = blk;
308                         return 0;
309                 }
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);
313         }
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);
317                         goto out_buf;
318                 }
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");
326                 *err = -EIO;
327                 goto out_buf;
328         }
329 #endif
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);
332                 goto out_buf;
333         }
334         dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
335         freedqbuf(buf);
336         return blk;
337 out_buf:
338         freedqbuf(buf);
339         return 0;
340 }
341
342 /* Insert reference to structure into the trie */
343 static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
344 {
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;
347         dqbuf_t buf;
348         int ret = 0, newson = 0, newact = 0;
349         u32 *ref;
350         uint newblk;
351
352         if (!(buf = getdqbuf()))
353                 return -ENOMEM;
354         if (!*treeblk) {
355                 ret = get_free_dqblk(filp, info);
356                 if (ret < 0)
357                         goto out_buf;
358                 *treeblk = ret;
359                 memset(buf, 0, V2_DQBLKSIZE);
360                 newact = 1;
361         }
362         else {
363                 if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
364                         printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
365                         goto out_buf;
366                 }
367         }
368         ref = (u32 *)buf;
369         newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
370         if (!newblk)
371                 newson = 1;
372         if (depth == V2_DQTREEDEPTH-1) {
373 #ifdef __QUOTA_V2_PARANOIA
374                 if (newblk) {
375                         printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]);
376                         ret = -EIO;
377                         goto out_buf;
378                 }
379 #endif
380                 newblk = find_free_dqentry(dquot, &ret);
381         }
382         else
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);
387         }
388         else if (newact && ret < 0)
389                 put_free_dqblk(filp, info, buf, *treeblk);
390 out_buf:
391         freedqbuf(buf);
392         return ret;
393 }
394
395 /* Wrapper for inserting quota structure into tree */
396 static inline int dq_insert_tree(struct dquot *dquot)
397 {
398         int tmp = V2_DQTREEOFF;
399         return do_insert_tree(dquot, &tmp, 0);
400 }
401
402 /*
403  *      We don't have to be afraid of deadlocks as we never have quotas on quota files...
404  */
405 static int v2_write_dquot(struct dquot *dquot)
406 {
407         int type = dquot->dq_type;
408         struct file *filp;
409         mm_segment_t fs;
410         loff_t offset;
411         ssize_t ret;
412         struct v2_disk_dqblk ddquot;
413
414         if (!dquot->dq_off)
415                 if ((ret = dq_insert_tree(dquot)) < 0) {
416                         printk(KERN_ERR "VFS: Error %d occured while creating quota.\n", ret);
417                         return ret;
418                 }
419         filp = sb_dqopt(dquot->dq_sb)->files[type];
420         offset = dquot->dq_off;
421         mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
422         fs = get_fs();
423         set_fs(KERNEL_DS);
424         ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
425         set_fs(fs);
426         if (ret != sizeof(struct v2_disk_dqblk)) {
427                 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", kdevname(dquot->dq_dev));
428                 if (ret >= 0)
429                         ret = -ENOSPC;
430         }
431         else
432                 ret = 0;
433         dqstats.writes++;
434         return ret;
435 }
436
437 /* Free dquot entry in data block */
438 static int free_dqentry(struct dquot *dquot, uint blk)
439 {
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();
444         int ret = 0;
445
446         if (!buf)
447                 return -ENOMEM;
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));
450                 goto out_buf;
451         }
452         if ((ret = read_blk(filp, blk, buf)) < 0) {
453                 printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
454                 goto out_buf;
455         }
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);
462                         goto out_buf;
463                 }
464         }
465         else {
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);
471                                 goto out_buf;
472                         }
473                 }
474                 else
475                         if ((ret = write_blk(filp, blk, buf)) < 0) {
476                                 printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
477                                 goto out_buf;
478                         }
479         }
480         dquot->dq_off = 0;      /* Quota is now unattached */
481 out_buf:
482         freedqbuf(buf);
483         return ret;
484 }
485
486 /* Remove reference to dquot from tree */
487 static int remove_tree(struct dquot *dquot, uint *blk, int depth)
488 {
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();
492         int ret = 0;
493         uint newblk;
494         u32 *ref = (u32 *)buf;
495         
496         if (!buf)
497                 return -ENOMEM;
498         if ((ret = read_blk(filp, *blk, buf)) < 0) {
499                 printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
500                 goto out_buf;
501         }
502         newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
503         if (depth == V2_DQTREEDEPTH-1) {
504                 ret = free_dqentry(dquot, newblk);
505                 newblk = 0;
506         }
507         else
508                 ret = remove_tree(dquot, &newblk, depth+1);
509         if (ret >= 0 && !newblk) {
510                 int i;
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);
515                         *blk = 0;
516                 }
517                 else
518                         if ((ret = write_blk(filp, *blk, buf)) < 0)
519                                 printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
520         }
521 out_buf:
522         freedqbuf(buf);
523         return ret;     
524 }
525
526 /* Delete dquot from tree */
527 static int v2_delete_dquot(struct dquot *dquot)
528 {
529         uint tmp = V2_DQTREEOFF;
530
531         if (!dquot->dq_off)     /* Even not allocated? */
532                 return 0;
533         return remove_tree(dquot, &tmp, 0);
534 }
535
536 /* Find entry in block */
537 static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
538 {
539         struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
540         dqbuf_t buf = getdqbuf();
541         loff_t ret = 0;
542         int i;
543         struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
544
545         if (!buf)
546                 return -ENOMEM;
547         if ((ret = read_blk(filp, blk, buf)) < 0) {
548                 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
549                 goto out_buf;
550         }
551         if (dquot->dq_id)
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;
555
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)))
559                                 break;
560         }
561         if (i == V2_DQSTRINBLK) {
562                 printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
563                 ret = -EIO;
564                 goto out_buf;
565         }
566         else
567                 ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
568 out_buf:
569         freedqbuf(buf);
570         return ret;
571 }
572
573 /* Find entry for given id in the tree */
574 static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
575 {
576         struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
577         dqbuf_t buf = getdqbuf();
578         loff_t ret = 0;
579         u32 *ref = (u32 *)buf;
580
581         if (!buf)
582                 return -ENOMEM;
583         if ((ret = read_blk(filp, blk, buf)) < 0) {
584                 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
585                 goto out_buf;
586         }
587         ret = 0;
588         blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
589         if (!blk)       /* No reference? */
590                 goto out_buf;
591         if (depth < V2_DQTREEDEPTH-1)
592                 ret = find_tree_dqentry(dquot, blk, depth+1);
593         else
594                 ret = find_block_dqentry(dquot, blk);
595 out_buf:
596         freedqbuf(buf);
597         return ret;
598 }
599
600 /* Find entry for given id in the tree - wrapper function */
601 static inline loff_t find_dqentry(struct dquot *dquot)
602 {
603         return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
604 }
605
606 static int v2_read_dquot(struct dquot *dquot)
607 {
608         int type = dquot->dq_type;
609         struct file *filp;
610         mm_segment_t fs;
611         loff_t offset;
612         struct v2_disk_dqblk ddquot;
613         int ret = 0;
614
615         filp = sb_dqopt(dquot->dq_sb)->files[type];
616
617 #ifdef __QUOTA_V2_PARANOIA
618         if (!filp || !dquot->dq_sb) {   /* Invalidated quota? */
619                 printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
620                 return -EIO;
621         }
622 #endif
623         offset = find_dqentry(dquot);
624         if (offset <= 0) {      /* Entry not present? */
625                 if (offset < 0)
626                         printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
627                 dquot->dq_off = 0;
628                 dquot->dq_flags |= DQ_FAKE;
629                 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
630                 ret = offset;
631         }
632         else {
633                 dquot->dq_off = offset;
634                 fs = get_fs();
635                 set_fs(KERNEL_DS);
636                 if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
637                         if (ret >= 0)
638                                 ret = -EIO;
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));
641                 }
642                 else
643                         ret = 0;
644                 set_fs(fs);
645                 disk2memdqb(&dquot->dq_dqb, &ddquot);
646         }
647         dqstats.reads++;
648         return ret;
649 }
650
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)
653 {
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);
658         else
659                 return v2_write_dquot(dquot);
660 }
661
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,
669 };
670
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
675 };
676
677 static int __init init_v2_quota_format(void)
678 {
679         return register_quota_format(&v2_quota_format);
680 }
681
682 static void __exit exit_v2_quota_format(void)
683 {
684         unregister_quota_format(&v2_quota_format);
685 }
686
687 EXPORT_NO_SYMBOLS;
688
689 module_init(init_v2_quota_format);
690 module_exit(exit_v2_quota_format);