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