Blame view

fs/quota/quota_tree.c 16.5 KB
1ccd14b9c   Jan Kara   quota: Split off ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   *	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
1ccd14b9c   Jan Kara   quota: Split off ...
24
25
26
27
28
29
30
31
32
33
34
  static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
  {
  	unsigned int epb = info->dqi_usable_bs >> 2;
  
  	depth = info->dqi_qtree_depth - depth - 1;
  	while (depth--)
  		id /= epb;
  	return id % epb;
  }
  
  /* Number of entries in one blocks */
7a2435d87   Jan Kara   quota: Remove sup...
35
  static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
1ccd14b9c   Jan Kara   quota: Split off ...
36
37
38
39
  {
  	return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))
  	       / info->dqi_entry_size;
  }
d26ac1a81   Jan Kara   quota: Remove dqb...
40
  static char *getdqbuf(size_t size)
1ccd14b9c   Jan Kara   quota: Split off ...
41
  {
d26ac1a81   Jan Kara   quota: Remove dqb...
42
  	char *buf = kmalloc(size, GFP_NOFS);
1ccd14b9c   Jan Kara   quota: Split off ...
43
  	if (!buf)
268157ba6   Jan Kara   quota: Coding sty...
44
45
46
  		printk(KERN_WARNING
  		       "VFS: Not enough memory for quota buffers.
  ");
1ccd14b9c   Jan Kara   quota: Split off ...
47
48
  	return buf;
  }
7a2435d87   Jan Kara   quota: Remove sup...
49
  static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
1ccd14b9c   Jan Kara   quota: Split off ...
50
51
52
53
  {
  	struct super_block *sb = info->dqi_sb;
  
  	memset(buf, 0, info->dqi_usable_bs);
d26ac1a81   Jan Kara   quota: Remove dqb...
54
  	return sb->s_op->quota_read(sb, info->dqi_type, buf,
1ccd14b9c   Jan Kara   quota: Split off ...
55
56
  	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
  }
7a2435d87   Jan Kara   quota: Remove sup...
57
  static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
1ccd14b9c   Jan Kara   quota: Split off ...
58
59
  {
  	struct super_block *sb = info->dqi_sb;
1907131bb   Jiaying Zhang   dquot: Detect par...
60
  	ssize_t ret;
1ccd14b9c   Jan Kara   quota: Split off ...
61

1907131bb   Jiaying Zhang   dquot: Detect par...
62
  	ret = sb->s_op->quota_write(sb, info->dqi_type, buf,
1ccd14b9c   Jan Kara   quota: Split off ...
63
  	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
1907131bb   Jiaying Zhang   dquot: Detect par...
64
  	if (ret != info->dqi_usable_bs) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
65
  		quota_error(sb, "dquota write failed");
1907131bb   Jiaying Zhang   dquot: Detect par...
66
67
68
69
  		if (ret >= 0)
  			ret = -EIO;
  	}
  	return ret;
1ccd14b9c   Jan Kara   quota: Split off ...
70
71
72
73
74
  }
  
  /* Remove empty block from list and return it */
  static int get_free_dqblk(struct qtree_mem_dqinfo *info)
  {
d26ac1a81   Jan Kara   quota: Remove dqb...
75
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  	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...
99
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
100
101
102
103
  	return ret;
  }
  
  /* Insert empty block to the list */
d26ac1a81   Jan Kara   quota: Remove dqb...
104
  static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)
1ccd14b9c   Jan Kara   quota: Split off ...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  {
  	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...
121
122
  static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
  			       uint blk)
1ccd14b9c   Jan Kara   quota: Split off ...
123
  {
d26ac1a81   Jan Kara   quota: Remove dqb...
124
  	char *tmpbuf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  	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...
155
  	kfree(tmpbuf);
1ccd14b9c   Jan Kara   quota: Split off ...
156
157
158
  	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...
159
160
  		quota_error(info->dqi_sb, "Can't write block (%u) "
  			    "with free entries", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
161
162
  	return 0;
  out_buf:
d26ac1a81   Jan Kara   quota: Remove dqb...
163
  	kfree(tmpbuf);
1ccd14b9c   Jan Kara   quota: Split off ...
164
165
166
167
  	return err;
  }
  
  /* Insert given block to the beginning of list with free entries */
268157ba6   Jan Kara   quota: Coding sty...
168
169
  static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf,
  			       uint blk)
1ccd14b9c   Jan Kara   quota: Split off ...
170
  {
d26ac1a81   Jan Kara   quota: Remove dqb...
171
  	char *tmpbuf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  	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...
192
  	kfree(tmpbuf);
1ccd14b9c   Jan Kara   quota: Split off ...
193
194
195
196
  	info->dqi_free_entry = blk;
  	mark_info_dirty(info->dqi_sb, info->dqi_type);
  	return 0;
  out_buf:
d26ac1a81   Jan Kara   quota: Remove dqb...
197
  	kfree(tmpbuf);
1ccd14b9c   Jan Kara   quota: Split off ...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  	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...
219
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
  	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...
237
  			kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
238
239
240
  			return 0;
  		}
  		memset(buf, 0, info->dqi_usable_bs);
268157ba6   Jan Kara   quota: Coding sty...
241
242
  		/* This is enough as the block is already zeroed and the entry
  		 * list is empty... */
1ccd14b9c   Jan Kara   quota: Split off ...
243
244
245
246
247
248
249
  		info->dqi_free_entry = blk;
  		mark_info_dirty(dquot->dq_sb, dquot->dq_type);
  	}
  	/* 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...
250
251
  			quota_error(dquot->dq_sb, "Can't remove block (%u) "
  				    "from entry free list", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
252
253
254
255
256
  			goto out_buf;
  		}
  	}
  	le16_add_cpu(&dh->dqdh_entries, 1);
  	/* Find free structure in block */
268157ba6   Jan Kara   quota: Coding sty...
257
258
259
260
261
262
  	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 ...
263
264
  #ifdef __QUOTA_QT_PARANOIA
  	if (i == qtree_dqstr_in_blk(info)) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
265
  		quota_error(dquot->dq_sb, "Data block full but it shouldn't");
1ccd14b9c   Jan Kara   quota: Split off ...
266
267
268
269
270
271
  		*err = -EIO;
  		goto out_buf;
  	}
  #endif
  	*err = write_blk(info, blk, buf);
  	if (*err < 0) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
272
273
  		quota_error(dquot->dq_sb, "Can't write quota data block %u",
  			    blk);
1ccd14b9c   Jan Kara   quota: Split off ...
274
275
276
277
278
  		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...
279
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
280
281
  	return blk;
  out_buf:
d26ac1a81   Jan Kara   quota: Remove dqb...
282
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
283
284
285
286
287
288
289
  	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...
290
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  	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...
307
308
  			quota_error(dquot->dq_sb, "Can't read tree quota "
  				    "block %u", *treeblk);
1ccd14b9c   Jan Kara   quota: Split off ...
309
310
311
312
313
314
315
316
317
318
  			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...
319
320
321
  			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 ...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  						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...
339
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
340
341
342
343
344
345
346
347
348
349
350
351
  	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;
  	return do_insert_tree(info, dquot, &tmp, 0);
  }
  
  /*
268157ba6   Jan Kara   quota: Coding sty...
352
353
   * We don't have to be afraid of deadlocks as we never have quotas on quota
   * files...
1ccd14b9c   Jan Kara   quota: Split off ...
354
355
356
357
358
359
   */
  int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
  {
  	int type = dquot->dq_type;
  	struct super_block *sb = dquot->dq_sb;
  	ssize_t ret;
d26ac1a81   Jan Kara   quota: Remove dqb...
360
  	char *ddquot = getdqbuf(info->dqi_entry_size);
1ccd14b9c   Jan Kara   quota: Split off ...
361
362
363
364
365
366
367
368
  
  	if (!ddquot)
  		return -ENOMEM;
  
  	/* dq_off is guarded by dqio_mutex */
  	if (!dquot->dq_off) {
  		ret = dq_insert_tree(info, dquot);
  		if (ret < 0) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
369
370
  			quota_error(sb, "Error %zd occurred while creating "
  				    "quota", ret);
d26ac1a81   Jan Kara   quota: Remove dqb...
371
  			kfree(ddquot);
1ccd14b9c   Jan Kara   quota: Split off ...
372
373
374
375
376
377
  			return ret;
  		}
  	}
  	spin_lock(&dq_data_lock);
  	info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
  	spin_unlock(&dq_data_lock);
d26ac1a81   Jan Kara   quota: Remove dqb...
378
379
  	ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,
  				    dquot->dq_off);
1ccd14b9c   Jan Kara   quota: Split off ...
380
  	if (ret != info->dqi_entry_size) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
381
  		quota_error(sb, "dquota write failed");
1ccd14b9c   Jan Kara   quota: Split off ...
382
383
384
385
386
  		if (ret >= 0)
  			ret = -ENOSPC;
  	} else {
  		ret = 0;
  	}
dde958885   Dmitry Monakhov   quota: Make quota...
387
  	dqstats_inc(DQST_WRITES);
d26ac1a81   Jan Kara   quota: Remove dqb...
388
  	kfree(ddquot);
1ccd14b9c   Jan Kara   quota: Split off ...
389
390
391
392
393
394
395
396
397
398
  
  	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...
399
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
400
401
402
403
404
  	int ret = 0;
  
  	if (!buf)
  		return -ENOMEM;
  	if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
405
406
407
  		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 ...
408
409
410
411
  		goto out_buf;
  	}
  	ret = read_blk(info, blk, buf);
  	if (ret < 0) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
412
413
  		quota_error(dquot->dq_sb, "Can't read quota data block %u",
  			    blk);
1ccd14b9c   Jan Kara   quota: Split off ...
414
415
416
417
418
419
420
421
422
  		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...
423
424
  			quota_error(dquot->dq_sb, "Can't move quota data block "
  				    "(%u) to free list", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
425
426
427
428
429
430
431
432
433
434
435
  			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...
436
437
  				quota_error(dquot->dq_sb, "Can't insert quota "
  				    "data block (%u) to free entry list", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
438
439
440
441
442
  				goto out_buf;
  			}
  		} else {
  			ret = write_blk(info, blk, buf);
  			if (ret < 0) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
443
444
  				quota_error(dquot->dq_sb, "Can't write quota "
  					    "data block %u", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
445
446
447
448
449
450
  				goto out_buf;
  			}
  		}
  	}
  	dquot->dq_off = 0;	/* Quota is now unattached */
  out_buf:
d26ac1a81   Jan Kara   quota: Remove dqb...
451
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
452
453
454
455
456
457
458
  	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...
459
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
460
461
462
463
464
465
466
467
  	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...
468
469
  		quota_error(dquot->dq_sb, "Can't read quota data block %u",
  			    *blk);
1ccd14b9c   Jan Kara   quota: Split off ...
470
471
472
473
474
475
476
477
478
479
480
481
482
  		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...
483
484
  		for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++)
  			;
1ccd14b9c   Jan Kara   quota: Split off ...
485
486
487
488
489
490
491
492
  		/* 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...
493
494
495
  				quota_error(dquot->dq_sb,
  					    "Can't write quota tree block %u",
  					    *blk);
1ccd14b9c   Jan Kara   quota: Split off ...
496
497
498
  		}
  	}
  out_buf:
d26ac1a81   Jan Kara   quota: Remove dqb...
499
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  	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...
518
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
519
520
521
522
523
524
525
526
  	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...
527
528
  		quota_error(dquot->dq_sb, "Can't read quota tree "
  			    "block %u", blk);
1ccd14b9c   Jan Kara   quota: Split off ...
529
530
  		goto out_buf;
  	}
268157ba6   Jan Kara   quota: Coding sty...
531
532
533
534
535
536
  	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 ...
537
  	if (i == qtree_dqstr_in_blk(info)) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
538
539
  		quota_error(dquot->dq_sb, "Quota for id %u referenced "
  			    "but not present", dquot->dq_id);
1ccd14b9c   Jan Kara   quota: Split off ...
540
541
542
543
544
545
546
  		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...
547
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
548
549
550
551
552
553
554
  	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...
555
  	char *buf = getdqbuf(info->dqi_usable_bs);
1ccd14b9c   Jan Kara   quota: Split off ...
556
557
558
559
560
561
562
  	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...
563
564
  		quota_error(dquot->dq_sb, "Can't read quota tree block %u",
  			    blk);
1ccd14b9c   Jan Kara   quota: Split off ...
565
566
567
568
569
570
571
572
573
574
575
  		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...
576
  	kfree(buf);
1ccd14b9c   Jan Kara   quota: Split off ...
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  	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)
  {
  	int type = dquot->dq_type;
  	struct super_block *sb = dquot->dq_sb;
  	loff_t offset;
d26ac1a81   Jan Kara   quota: Remove dqb...
592
  	char *ddquot;
1ccd14b9c   Jan Kara   quota: Split off ...
593
594
595
596
597
  	int ret = 0;
  
  #ifdef __QUOTA_QT_PARANOIA
  	/* Invalidated quota? */
  	if (!sb_dqopt(dquot->dq_sb)->files[type]) {
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
598
  		quota_error(sb, "Quota invalidated while reading!");
1ccd14b9c   Jan Kara   quota: Split off ...
599
600
601
602
603
604
605
606
  		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)
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
607
608
  				quota_error(sb, "Can't read quota structure "
  					    "for id %u", dquot->dq_id);
1ccd14b9c   Jan Kara   quota: Split off ...
609
610
611
612
613
614
615
616
617
618
619
  			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...
620
621
  	ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size,
  				   dquot->dq_off);
1ccd14b9c   Jan Kara   quota: Split off ...
622
623
624
  	if (ret != info->dqi_entry_size) {
  		if (ret >= 0)
  			ret = -EIO;
fb5ffb0e1   Jiaying Zhang   quota: Change quo...
625
626
  		quota_error(sb, "Error while reading quota structure for id %u",
  			    dquot->dq_id);
1ccd14b9c   Jan Kara   quota: Split off ...
627
628
  		set_bit(DQ_FAKE_B, &dquot->dq_flags);
  		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
d26ac1a81   Jan Kara   quota: Remove dqb...
629
  		kfree(ddquot);
1ccd14b9c   Jan Kara   quota: Split off ...
630
631
632
633
634
635
636
637
638
639
  		goto out;
  	}
  	spin_lock(&dq_data_lock);
  	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);
  	spin_unlock(&dq_data_lock);
d26ac1a81   Jan Kara   quota: Remove dqb...
640
  	kfree(ddquot);
1ccd14b9c   Jan Kara   quota: Split off ...
641
  out:
dde958885   Dmitry Monakhov   quota: Make quota...
642
  	dqstats_inc(DQST_READS);
1ccd14b9c   Jan Kara   quota: Split off ...
643
644
645
646
647
648
649
650
  	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...
651
652
  	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 ...
653
654
655
656
  		return qtree_delete_dquot(info, dquot);
  	return 0;
  }
  EXPORT_SYMBOL(qtree_release_dquot);