Blame view

fs/quota/quota_tree.c 18.2 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1ccd14b9c   Jan Kara   quota: Split off ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   *	vfsv0 quota IO operations on file
   */
  
  #include <linux/errno.h>
  #include <linux/fs.h>
  #include <linux/mount.h>
  #include <linux/dqblk_v2.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/quotaops.h>
  
  #include <asm/byteorder.h>
  
  #include "quota_tree.h"
  
  MODULE_AUTHOR("Jan Kara");
  MODULE_DESCRIPTION("Quota trie support");
  MODULE_LICENSE("GPL");
  
  #define __QUOTA_QT_PARANOIA
0066373d9   Jan Kara   quota_v2: Impleme...
25
  static int __get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
1ccd14b9c   Jan Kara   quota: Split off ...
26
27
28
29
30
31
32
33
  {
  	unsigned int epb = info->dqi_usable_bs >> 2;
  
  	depth = info->dqi_qtree_depth - depth - 1;
  	while (depth--)
  		id /= epb;
  	return id % epb;
  }
0066373d9   Jan Kara   quota_v2: Impleme...
34
35
36
37
38
39
  static int get_index(struct qtree_mem_dqinfo *info, struct kqid qid, int depth)
  {
  	qid_t id = from_kqid(&init_user_ns, qid);
  
  	return __get_index(info, id, depth);
  }
1ccd14b9c   Jan Kara   quota: Split off ...
40
  /* Number of entries in one blocks */
7a2435d87   Jan Kara   quota: Remove sup...
41
  static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
1ccd14b9c   Jan Kara   quota: Split off ...
42
43
44
45
  {
  	return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))
  	       / info->dqi_entry_size;
  }
d26ac1a81   Jan Kara   quota: Remove dqb...
46
  static char *getdqbuf(size_t size)
1ccd14b9c   Jan Kara   quota: Split off ...
47
  {
d26ac1a81   Jan Kara   quota: Remove dqb...
48
  	char *buf = kmalloc(size, GFP_NOFS);
1ccd14b9c   Jan Kara   quota: Split off ...
49
  	if (!buf)
268157ba6   Jan Kara   quota: Coding sty...
50
51
52
  		printk(KERN_WARNING
  		       "VFS: Not enough memory for quota buffers.
  ");
1ccd14b9c   Jan Kara   quota: Split off ...
53
54
  	return buf;
  }
7a2435d87   Jan Kara   quota: Remove sup...
55
  static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
1ccd14b9c   Jan Kara   quota: Split off ...
56
57
58
59
  {
  	struct super_block *sb = info->dqi_sb;
  
  	memset(buf, 0, info->dqi_usable_bs);
d26ac1a81   Jan Kara   quota: Remove dqb...
60
  	return sb->s_op->quota_read(sb, info->dqi_type, buf,
1ccd14b9c   Jan Kara   quota: Split off ...
61
62
  	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
  }
7a2435d87   Jan Kara   quota: Remove sup...
63
  static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
1ccd14b9c   Jan Kara   quota: Split off ...
64
65
  {
  	struct super_block *sb = info->dqi_sb;
1907131bb   Jiaying Zhang   dquot: Detect par...
66
  	ssize_t ret;
1ccd14b9c   Jan Kara   quota: Split off ...
67

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