1/*
2 *	vfsv0 quota IO operations on file
3 */
4
5#include <linux/errno.h>
6#include <linux/fs.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
15#include <asm/byteorder.h>
16
17MODULE_AUTHOR("Jan Kara");
18MODULE_DESCRIPTION("Quota format v2 support");
19MODULE_LICENSE("GPL");
20
21#define __QUOTA_V2_PARANOIA
22
23typedef char *dqbuf_t;
24
25#define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
26#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
27
28/* Check whether given file is really vfsv0 quotafile */
29static int v2_check_quota_file(struct super_block *sb, int type)
30{
31	struct v2_disk_dqheader dqhead;
32	ssize_t size;
33	static const uint quota_magics[] = V2_INITQMAGICS;
34	static const uint quota_versions[] = V2_INITQVERSIONS;
35
36	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
37	if (size != sizeof(struct v2_disk_dqheader)) {
38		printk("quota_v2: failed read expected=%zd got=%zd\n",
39			sizeof(struct v2_disk_dqheader), size);
40		return 0;
41	}
42	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
43	    le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
44		return 0;
45	return 1;
46}
47
48/* Read information header from quota file */
49static int v2_read_file_info(struct super_block *sb, int type)
50{
51	struct v2_disk_dqinfo dinfo;
52	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
53	ssize_t size;
54
55	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
56	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
57	if (size != sizeof(struct v2_disk_dqinfo)) {
58		printk(KERN_WARNING "Can't read info structure on device %s.\n",
59			sb->s_id);
60		return -1;
61	}
62	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
63	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
64	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
65	info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
66	info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
67	info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
68	return 0;
69}
70
71/* Write information header to quota file */
72static int v2_write_file_info(struct super_block *sb, int type)
73{
74	struct v2_disk_dqinfo dinfo;
75	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
76	ssize_t size;
77
78	spin_lock(&dq_data_lock);
79	info->dqi_flags &= ~DQF_INFO_DIRTY;
80	dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
81	dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
82	dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
83	spin_unlock(&dq_data_lock);
84	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
85	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
86	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
87	size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
88	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
89	if (size != sizeof(struct v2_disk_dqinfo)) {
90		printk(KERN_WARNING "Can't write info structure on device %s.\n",
91			sb->s_id);
92		return -1;
93	}
94	return 0;
95}
96
97static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
98{
99	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
100	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
101	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
102	m->dqb_itime = le64_to_cpu(d->dqb_itime);
103	m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
104	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
105	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
106	m->dqb_btime = le64_to_cpu(d->dqb_btime);
107}
108
109static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
110{
111	d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
112	d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
113	d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
114	d->dqb_itime = cpu_to_le64(m->dqb_itime);
115	d->dqb_bhardlimit = cpu_to_le32(m->dqb_bhardlimit);
116	d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
117	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
118	d->dqb_btime = cpu_to_le64(m->dqb_btime);
119	d->dqb_id = cpu_to_le32(id);
120}
121
122static dqbuf_t getdqbuf(void)
123{
124	dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_NOFS);
125	if (!buf)
126		printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
127	return buf;
128}
129
130static inline void freedqbuf(dqbuf_t buf)
131{
132	kfree(buf);
133}
134
135static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
136{
137	memset(buf, 0, V2_DQBLKSIZE);
138	return sb->s_op->quota_read(sb, type, (char *)buf,
139	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
140}
141
142static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
143{
144	return sb->s_op->quota_write(sb, type, (char *)buf,
145	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
146}
147
148/* Remove empty block from list and return it */
149static int get_free_dqblk(struct super_block *sb, int type)
150{
151	dqbuf_t buf = getdqbuf();
152	struct mem_dqinfo *info = sb_dqinfo(sb, type);
153	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
154	int ret, blk;
155
156	if (!buf)
157		return -ENOMEM;
158	if (info->u.v2_i.dqi_free_blk) {
159		blk = info->u.v2_i.dqi_free_blk;
160		if ((ret = read_blk(sb, type, blk, buf)) < 0)
161			goto out_buf;
162		info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
163	}
164	else {
165		memset(buf, 0, V2_DQBLKSIZE);
166		/* Assure block allocation... */
167		if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
168			goto out_buf;
169		blk = info->u.v2_i.dqi_blocks++;
170	}
171	mark_info_dirty(sb, type);
172	ret = blk;
173out_buf:
174	freedqbuf(buf);
175	return ret;
176}
177
178/* Insert empty block to the list */
179static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
180{
181	struct mem_dqinfo *info = sb_dqinfo(sb, type);
182	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
183	int err;
184
185	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
186	dh->dqdh_prev_free = cpu_to_le32(0);
187	dh->dqdh_entries = cpu_to_le16(0);
188	info->u.v2_i.dqi_free_blk = blk;
189	mark_info_dirty(sb, type);
190	/* Some strange block. We had better leave it... */
191	if ((err = write_blk(sb, type, blk, buf)) < 0)
192		return err;
193	return 0;
194}
195
196/* Remove given block from the list of blocks with free entries */
197static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
198{
199	dqbuf_t tmpbuf = getdqbuf();
200	struct mem_dqinfo *info = sb_dqinfo(sb, type);
201	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
202	uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
203	int err;
204
205	if (!tmpbuf)
206		return -ENOMEM;
207	if (nextblk) {
208		if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
209			goto out_buf;
210		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
211		if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
212			goto out_buf;
213	}
214	if (prevblk) {
215		if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
216			goto out_buf;
217		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
218		if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
219			goto out_buf;
220	}
221	else {
222		info->u.v2_i.dqi_free_entry = nextblk;
223		mark_info_dirty(sb, type);
224	}
225	freedqbuf(tmpbuf);
226	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
227	/* No matter whether write succeeds block is out of list */
228	if (write_blk(sb, type, blk, buf) < 0)
229		printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
230	return 0;
231out_buf:
232	freedqbuf(tmpbuf);
233	return err;
234}
235
236/* Insert given block to the beginning of list with free entries */
237static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
238{
239	dqbuf_t tmpbuf = getdqbuf();
240	struct mem_dqinfo *info = sb_dqinfo(sb, type);
241	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
242	int err;
243
244	if (!tmpbuf)
245		return -ENOMEM;
246	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
247	dh->dqdh_prev_free = cpu_to_le32(0);
248	if ((err = write_blk(sb, type, blk, buf)) < 0)
249		goto out_buf;
250	if (info->u.v2_i.dqi_free_entry) {
251		if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
252			goto out_buf;
253		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
254		if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
255			goto out_buf;
256	}
257	freedqbuf(tmpbuf);
258	info->u.v2_i.dqi_free_entry = blk;
259	mark_info_dirty(sb, type);
260	return 0;
261out_buf:
262	freedqbuf(tmpbuf);
263	return err;
264}
265
266/* Find space for dquot */
267static uint find_free_dqentry(struct dquot *dquot, int *err)
268{
269	struct super_block *sb = dquot->dq_sb;
270	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
271	uint blk, i;
272	struct v2_disk_dqdbheader *dh;
273	struct v2_disk_dqblk *ddquot;
274	struct v2_disk_dqblk fakedquot;
275	dqbuf_t buf;
276
277	*err = 0;
278	if (!(buf = getdqbuf())) {
279		*err = -ENOMEM;
280		return 0;
281	}
282	dh = (struct v2_disk_dqdbheader *)buf;
283	ddquot = GETENTRIES(buf);
284	if (info->u.v2_i.dqi_free_entry) {
285		blk = info->u.v2_i.dqi_free_entry;
286		if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
287			goto out_buf;
288	}
289	else {
290		blk = get_free_dqblk(sb, dquot->dq_type);
291		if ((int)blk < 0) {
292			*err = blk;
293			freedqbuf(buf);
294			return 0;
295		}
296		memset(buf, 0, V2_DQBLKSIZE);
297		/* This is enough as block is already zeroed and entry list is empty... */
298		info->u.v2_i.dqi_free_entry = blk;
299		mark_info_dirty(sb, dquot->dq_type);
300	}
301	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
302		if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
303			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
304			goto out_buf;
305		}
306	dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
307	memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
308	/* Find free structure in block */
309	for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
310#ifdef __QUOTA_V2_PARANOIA
311	if (i == V2_DQSTRINBLK) {
312		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
313		*err = -EIO;
314		goto out_buf;
315	}
316#endif
317	if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
318		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
319		goto out_buf;
320	}
321	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
322	freedqbuf(buf);
323	return blk;
324out_buf:
325	freedqbuf(buf);
326	return 0;
327}
328
329/* Insert reference to structure into the trie */
330static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
331{
332	struct super_block *sb = dquot->dq_sb;
333	dqbuf_t buf;
334	int ret = 0, newson = 0, newact = 0;
335	__le32 *ref;
336	uint newblk;
337
338	if (!(buf = getdqbuf()))
339		return -ENOMEM;
340	if (!*treeblk) {
341		ret = get_free_dqblk(sb, dquot->dq_type);
342		if (ret < 0)
343			goto out_buf;
344		*treeblk = ret;
345		memset(buf, 0, V2_DQBLKSIZE);
346		newact = 1;
347	}
348	else {
349		if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
350			printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
351			goto out_buf;
352		}
353	}
354	ref = (__le32 *)buf;
355	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
356	if (!newblk)
357		newson = 1;
358	if (depth == V2_DQTREEDEPTH-1) {
359#ifdef __QUOTA_V2_PARANOIA
360		if (newblk) {
361			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
362			ret = -EIO;
363			goto out_buf;
364		}
365#endif
366		newblk = find_free_dqentry(dquot, &ret);
367	}
368	else
369		ret = do_insert_tree(dquot, &newblk, depth+1);
370	if (newson && ret >= 0) {
371		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
372		ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
373	}
374	else if (newact && ret < 0)
375		put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
376out_buf:
377	freedqbuf(buf);
378	return ret;
379}
380
381/* Wrapper for inserting quota structure into tree */
382static inline int dq_insert_tree(struct dquot *dquot)
383{
384	int tmp = V2_DQTREEOFF;
385	return do_insert_tree(dquot, &tmp, 0);
386}
387
388/*
389 *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
390 */
391static int v2_write_dquot(struct dquot *dquot)
392{
393	int type = dquot->dq_type;
394	ssize_t ret;
395	struct v2_disk_dqblk ddquot, empty;
396
397	/* dq_off is guarded by dqio_mutex */
398	if (!dquot->dq_off)
399		if ((ret = dq_insert_tree(dquot)) < 0) {
400			printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
401			return ret;
402		}
403	spin_lock(&dq_data_lock);
404	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
405	/* Argh... We may need to write structure full of zeroes but that would be
406	 * treated as an empty place by the rest of the code. Format change would
407	 * be definitely cleaner but the problems probably are not worth it */
408	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
409	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
410		ddquot.dqb_itime = cpu_to_le64(1);
411	spin_unlock(&dq_data_lock);
412	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
413	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
414	if (ret != sizeof(struct v2_disk_dqblk)) {
415		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
416		if (ret >= 0)
417			ret = -ENOSPC;
418	}
419	else
420		ret = 0;
421	dqstats.writes++;
422
423	return ret;
424}
425
426/* Free dquot entry in data block */
427static int free_dqentry(struct dquot *dquot, uint blk)
428{
429	struct super_block *sb = dquot->dq_sb;
430	int type = dquot->dq_type;
431	struct v2_disk_dqdbheader *dh;
432	dqbuf_t buf = getdqbuf();
433	int ret = 0;
434
435	if (!buf)
436		return -ENOMEM;
437	if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
438		printk(KERN_ERR "VFS: Quota structure has offset to other "
439		  "block (%u) than it should (%u).\n", blk,
440		  (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
441		goto out_buf;
442	}
443	if ((ret = read_blk(sb, type, blk, buf)) < 0) {
444		printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
445		goto out_buf;
446	}
447	dh = (struct v2_disk_dqdbheader *)buf;
448	dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
449	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
450		if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
451		    (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
452			printk(KERN_ERR "VFS: Can't move quota data block (%u) "
453			  "to free list.\n", blk);
454			goto out_buf;
455		}
456	}
457	else {
458		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
459		  sizeof(struct v2_disk_dqblk));
460		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
461			/* Insert will write block itself */
462			if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
463				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
464				goto out_buf;
465			}
466		}
467		else
468			if ((ret = write_blk(sb, type, blk, buf)) < 0) {
469				printk(KERN_ERR "VFS: Can't write quota data "
470				  "block %u\n", blk);
471				goto out_buf;
472			}
473	}
474	dquot->dq_off = 0;	/* Quota is now unattached */
475out_buf:
476	freedqbuf(buf);
477	return ret;
478}
479
480/* Remove reference to dquot from tree */
481static int remove_tree(struct dquot *dquot, uint *blk, int depth)
482{
483	struct super_block *sb = dquot->dq_sb;
484	int type = dquot->dq_type;
485	dqbuf_t buf = getdqbuf();
486	int ret = 0;
487	uint newblk;
488	__le32 *ref = (__le32 *)buf;
489
490	if (!buf)
491		return -ENOMEM;
492	if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
493		printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
494		goto out_buf;
495	}
496	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
497	if (depth == V2_DQTREEDEPTH-1) {
498		ret = free_dqentry(dquot, newblk);
499		newblk = 0;
500	}
501	else
502		ret = remove_tree(dquot, &newblk, depth+1);
503	if (ret >= 0 && !newblk) {
504		int i;
505		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
506		for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);	/* Block got empty? */
507		/* Don't put the root block into the free block list */
508		if (i == V2_DQBLKSIZE && *blk != V2_DQTREEOFF) {
509			put_free_dqblk(sb, type, buf, *blk);
510			*blk = 0;
511		}
512		else
513			if ((ret = write_blk(sb, type, *blk, buf)) < 0)
514				printk(KERN_ERR "VFS: Can't write quota tree "
515				  "block %u.\n", *blk);
516	}
517out_buf:
518	freedqbuf(buf);
519	return ret;
520}
521
522/* Delete dquot from tree */
523static int v2_delete_dquot(struct dquot *dquot)
524{
525	uint tmp = V2_DQTREEOFF;
526
527	if (!dquot->dq_off)	/* Even not allocated? */
528		return 0;
529	return remove_tree(dquot, &tmp, 0);
530}
531
532/* Find entry in block */
533static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
534{
535	dqbuf_t buf = getdqbuf();
536	loff_t ret = 0;
537	int i;
538	struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
539
540	if (!buf)
541		return -ENOMEM;
542	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
543		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
544		goto out_buf;
545	}
546	if (dquot->dq_id)
547		for (i = 0; i < V2_DQSTRINBLK &&
548		     le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
549	else {	/* ID 0 as a bit more complicated searching... */
550		struct v2_disk_dqblk fakedquot;
551
552		memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
553		for (i = 0; i < V2_DQSTRINBLK; i++)
554			if (!le32_to_cpu(ddquot[i].dqb_id) &&
555			    memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
556				break;
557	}
558	if (i == V2_DQSTRINBLK) {
559		printk(KERN_ERR "VFS: Quota for id %u referenced "
560		  "but not present.\n", dquot->dq_id);
561		ret = -EIO;
562		goto out_buf;
563	}
564	else
565		ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
566		  v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
567out_buf:
568	freedqbuf(buf);
569	return ret;
570}
571
572/* Find entry for given id in the tree */
573static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
574{
575	dqbuf_t buf = getdqbuf();
576	loff_t ret = 0;
577	__le32 *ref = (__le32 *)buf;
578
579	if (!buf)
580		return -ENOMEM;
581	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
582		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
583		goto out_buf;
584	}
585	ret = 0;
586	blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
587	if (!blk)	/* No reference? */
588		goto out_buf;
589	if (depth < V2_DQTREEDEPTH-1)
590		ret = find_tree_dqentry(dquot, blk, depth+1);
591	else
592		ret = find_block_dqentry(dquot, blk);
593out_buf:
594	freedqbuf(buf);
595	return ret;
596}
597
598/* Find entry for given id in the tree - wrapper function */
599static inline loff_t find_dqentry(struct dquot *dquot)
600{
601	return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
602}
603
604static int v2_read_dquot(struct dquot *dquot)
605{
606	int type = dquot->dq_type;
607	loff_t offset;
608	struct v2_disk_dqblk ddquot, empty;
609	int ret = 0;
610
611#ifdef __QUOTA_V2_PARANOIA
612	/* Invalidated quota? */
613	if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
614		printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
615		return -EIO;
616	}
617#endif
618	offset = find_dqentry(dquot);
619	if (offset <= 0) {	/* Entry not present? */
620		if (offset < 0)
621			printk(KERN_ERR "VFS: Can't read quota "
622			  "structure for id %u.\n", dquot->dq_id);
623		dquot->dq_off = 0;
624		set_bit(DQ_FAKE_B, &dquot->dq_flags);
625		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
626		ret = offset;
627	}
628	else {
629		dquot->dq_off = offset;
630		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
631		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
632		    != sizeof(struct v2_disk_dqblk)) {
633			if (ret >= 0)
634				ret = -EIO;
635			printk(KERN_ERR "VFS: Error while reading quota "
636			  "structure for id %u.\n", dquot->dq_id);
637			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
638		}
639		else {
640			ret = 0;
641			/* We need to escape back all-zero structure */
642			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
643			empty.dqb_itime = cpu_to_le64(1);
644			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
645				ddquot.dqb_itime = 0;
646		}
647		disk2memdqb(&dquot->dq_dqb, &ddquot);
648		if (!dquot->dq_dqb.dqb_bhardlimit &&
649			!dquot->dq_dqb.dqb_bsoftlimit &&
650			!dquot->dq_dqb.dqb_ihardlimit &&
651			!dquot->dq_dqb.dqb_isoftlimit)
652			set_bit(DQ_FAKE_B, &dquot->dq_flags);
653	}
654	dqstats.reads++;
655
656	return ret;
657}
658
659/* Check whether dquot should not be deleted. We know we are
660 * the only one operating on dquot (thanks to dq_lock) */
661static int v2_release_dquot(struct dquot *dquot)
662{
663	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
664		return v2_delete_dquot(dquot);
665	return 0;
666}
667
668static struct quota_format_ops v2_format_ops = {
669	.check_quota_file	= v2_check_quota_file,
670	.read_file_info		= v2_read_file_info,
671	.write_file_info	= v2_write_file_info,
672	.free_file_info		= NULL,
673	.read_dqblk		= v2_read_dquot,
674	.commit_dqblk		= v2_write_dquot,
675	.release_dqblk		= v2_release_dquot,
676};
677
678static struct quota_format_type v2_quota_format = {
679	.qf_fmt_id	= QFMT_VFS_V0,
680	.qf_ops		= &v2_format_ops,
681	.qf_owner	= THIS_MODULE
682};
683
684static int __init init_v2_quota_format(void)
685{
686	return register_quota_format(&v2_quota_format);
687}
688
689static void __exit exit_v2_quota_format(void)
690{
691	unregister_quota_format(&v2_quota_format);
692}
693
694module_init(init_v2_quota_format);
695module_exit(exit_v2_quota_format);
696