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