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