aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/quota/quota_tree.c104
1 files changed, 49 insertions, 55 deletions
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c
index 953404c95b17..3a5a90c08962 100644
--- a/fs/quota/quota_tree.c
+++ b/fs/quota/quota_tree.c
@@ -22,8 +22,6 @@ MODULE_LICENSE("GPL");
22 22
23#define __QUOTA_QT_PARANOIA 23#define __QUOTA_QT_PARANOIA
24 24
25typedef char *dqbuf_t;
26
27static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth) 25static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
28{ 26{
29 unsigned int epb = info->dqi_usable_bs >> 2; 27 unsigned int epb = info->dqi_usable_bs >> 2;
@@ -41,40 +39,35 @@ static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
41 / info->dqi_entry_size; 39 / info->dqi_entry_size;
42} 40}
43 41
44static dqbuf_t getdqbuf(size_t size) 42static char *getdqbuf(size_t size)
45{ 43{
46 dqbuf_t buf = kmalloc(size, GFP_NOFS); 44 char *buf = kmalloc(size, GFP_NOFS);
47 if (!buf) 45 if (!buf)
48 printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n"); 46 printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
49 return buf; 47 return buf;
50} 48}
51 49
52static inline void freedqbuf(dqbuf_t buf) 50static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
53{
54 kfree(buf);
55}
56
57static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
58{ 51{
59 struct super_block *sb = info->dqi_sb; 52 struct super_block *sb = info->dqi_sb;
60 53
61 memset(buf, 0, info->dqi_usable_bs); 54 memset(buf, 0, info->dqi_usable_bs);
62 return sb->s_op->quota_read(sb, info->dqi_type, (char *)buf, 55 return sb->s_op->quota_read(sb, info->dqi_type, buf,
63 info->dqi_usable_bs, blk << info->dqi_blocksize_bits); 56 info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
64} 57}
65 58
66static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf) 59static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
67{ 60{
68 struct super_block *sb = info->dqi_sb; 61 struct super_block *sb = info->dqi_sb;
69 62
70 return sb->s_op->quota_write(sb, info->dqi_type, (char *)buf, 63 return sb->s_op->quota_write(sb, info->dqi_type, buf,
71 info->dqi_usable_bs, blk << info->dqi_blocksize_bits); 64 info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
72} 65}
73 66
74/* Remove empty block from list and return it */ 67/* Remove empty block from list and return it */
75static int get_free_dqblk(struct qtree_mem_dqinfo *info) 68static int get_free_dqblk(struct qtree_mem_dqinfo *info)
76{ 69{
77 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 70 char *buf = getdqbuf(info->dqi_usable_bs);
78 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 71 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
79 int ret, blk; 72 int ret, blk;
80 73
@@ -98,12 +91,12 @@ static int get_free_dqblk(struct qtree_mem_dqinfo *info)
98 mark_info_dirty(info->dqi_sb, info->dqi_type); 91 mark_info_dirty(info->dqi_sb, info->dqi_type);
99 ret = blk; 92 ret = blk;
100out_buf: 93out_buf:
101 freedqbuf(buf); 94 kfree(buf);
102 return ret; 95 return ret;
103} 96}
104 97
105/* Insert empty block to the list */ 98/* Insert empty block to the list */
106static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) 99static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk)
107{ 100{
108 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 101 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
109 int err; 102 int err;
@@ -120,9 +113,9 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
120} 113}
121 114
122/* Remove given block from the list of blocks with free entries */ 115/* Remove given block from the list of blocks with free entries */
123static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) 116static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk)
124{ 117{
125 dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs); 118 char *tmpbuf = getdqbuf(info->dqi_usable_bs);
126 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 119 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
127 uint nextblk = le32_to_cpu(dh->dqdh_next_free); 120 uint nextblk = le32_to_cpu(dh->dqdh_next_free);
128 uint prevblk = le32_to_cpu(dh->dqdh_prev_free); 121 uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
@@ -153,21 +146,21 @@ static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint
153 info->dqi_free_entry = nextblk; 146 info->dqi_free_entry = nextblk;
154 mark_info_dirty(info->dqi_sb, info->dqi_type); 147 mark_info_dirty(info->dqi_sb, info->dqi_type);
155 } 148 }
156 freedqbuf(tmpbuf); 149 kfree(tmpbuf);
157 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); 150 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
158 /* No matter whether write succeeds block is out of list */ 151 /* No matter whether write succeeds block is out of list */
159 if (write_blk(info, blk, buf) < 0) 152 if (write_blk(info, blk, buf) < 0)
160 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk); 153 printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
161 return 0; 154 return 0;
162out_buf: 155out_buf:
163 freedqbuf(tmpbuf); 156 kfree(tmpbuf);
164 return err; 157 return err;
165} 158}
166 159
167/* Insert given block to the beginning of list with free entries */ 160/* Insert given block to the beginning of list with free entries */
168static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk) 161static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, uint blk)
169{ 162{
170 dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs); 163 char *tmpbuf = getdqbuf(info->dqi_usable_bs);
171 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; 164 struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
172 int err; 165 int err;
173 166
@@ -188,12 +181,12 @@ static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint
188 if (err < 0) 181 if (err < 0)
189 goto out_buf; 182 goto out_buf;
190 } 183 }
191 freedqbuf(tmpbuf); 184 kfree(tmpbuf);
192 info->dqi_free_entry = blk; 185 info->dqi_free_entry = blk;
193 mark_info_dirty(info->dqi_sb, info->dqi_type); 186 mark_info_dirty(info->dqi_sb, info->dqi_type);
194 return 0; 187 return 0;
195out_buf: 188out_buf:
196 freedqbuf(tmpbuf); 189 kfree(tmpbuf);
197 return err; 190 return err;
198} 191}
199 192
@@ -215,7 +208,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
215{ 208{
216 uint blk, i; 209 uint blk, i;
217 struct qt_disk_dqdbheader *dh; 210 struct qt_disk_dqdbheader *dh;
218 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 211 char *buf = getdqbuf(info->dqi_usable_bs);
219 char *ddquot; 212 char *ddquot;
220 213
221 *err = 0; 214 *err = 0;
@@ -233,7 +226,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
233 blk = get_free_dqblk(info); 226 blk = get_free_dqblk(info);
234 if ((int)blk < 0) { 227 if ((int)blk < 0) {
235 *err = blk; 228 *err = blk;
236 freedqbuf(buf); 229 kfree(buf);
237 return 0; 230 return 0;
238 } 231 }
239 memset(buf, 0, info->dqi_usable_bs); 232 memset(buf, 0, info->dqi_usable_bs);
@@ -253,9 +246,10 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
253 } 246 }
254 le16_add_cpu(&dh->dqdh_entries, 1); 247 le16_add_cpu(&dh->dqdh_entries, 1);
255 /* Find free structure in block */ 248 /* Find free structure in block */
256 for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader); 249 for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader);
257 i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot); 250 i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot);
258 i++, ddquot += info->dqi_entry_size); 251 i++, ddquot += info->dqi_entry_size)
252 ;
259#ifdef __QUOTA_QT_PARANOIA 253#ifdef __QUOTA_QT_PARANOIA
260 if (i == qtree_dqstr_in_blk(info)) { 254 if (i == qtree_dqstr_in_blk(info)) {
261 printk(KERN_ERR "VFS: find_free_dqentry(): Data block full " 255 printk(KERN_ERR "VFS: find_free_dqentry(): Data block full "
@@ -273,10 +267,10 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
273 dquot->dq_off = (blk << info->dqi_blocksize_bits) + 267 dquot->dq_off = (blk << info->dqi_blocksize_bits) +
274 sizeof(struct qt_disk_dqdbheader) + 268 sizeof(struct qt_disk_dqdbheader) +
275 i * info->dqi_entry_size; 269 i * info->dqi_entry_size;
276 freedqbuf(buf); 270 kfree(buf);
277 return blk; 271 return blk;
278out_buf: 272out_buf:
279 freedqbuf(buf); 273 kfree(buf);
280 return 0; 274 return 0;
281} 275}
282 276
@@ -284,7 +278,7 @@ out_buf:
284static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, 278static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
285 uint *treeblk, int depth) 279 uint *treeblk, int depth)
286{ 280{
287 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 281 char *buf = getdqbuf(info->dqi_usable_bs);
288 int ret = 0, newson = 0, newact = 0; 282 int ret = 0, newson = 0, newact = 0;
289 __le32 *ref; 283 __le32 *ref;
290 uint newblk; 284 uint newblk;
@@ -333,7 +327,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
333 put_free_dqblk(info, buf, *treeblk); 327 put_free_dqblk(info, buf, *treeblk);
334 } 328 }
335out_buf: 329out_buf:
336 freedqbuf(buf); 330 kfree(buf);
337 return ret; 331 return ret;
338} 332}
339 333
@@ -353,7 +347,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
353 int type = dquot->dq_type; 347 int type = dquot->dq_type;
354 struct super_block *sb = dquot->dq_sb; 348 struct super_block *sb = dquot->dq_sb;
355 ssize_t ret; 349 ssize_t ret;
356 dqbuf_t ddquot = getdqbuf(info->dqi_entry_size); 350 char *ddquot = getdqbuf(info->dqi_entry_size);
357 351
358 if (!ddquot) 352 if (!ddquot)
359 return -ENOMEM; 353 return -ENOMEM;
@@ -364,15 +358,15 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
364 if (ret < 0) { 358 if (ret < 0) {
365 printk(KERN_ERR "VFS: Error %zd occurred while " 359 printk(KERN_ERR "VFS: Error %zd occurred while "
366 "creating quota.\n", ret); 360 "creating quota.\n", ret);
367 freedqbuf(ddquot); 361 kfree(ddquot);
368 return ret; 362 return ret;
369 } 363 }
370 } 364 }
371 spin_lock(&dq_data_lock); 365 spin_lock(&dq_data_lock);
372 info->dqi_ops->mem2disk_dqblk(ddquot, dquot); 366 info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
373 spin_unlock(&dq_data_lock); 367 spin_unlock(&dq_data_lock);
374 ret = sb->s_op->quota_write(sb, type, (char *)ddquot, 368 ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,
375 info->dqi_entry_size, dquot->dq_off); 369 dquot->dq_off);
376 if (ret != info->dqi_entry_size) { 370 if (ret != info->dqi_entry_size) {
377 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", 371 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
378 sb->s_id); 372 sb->s_id);
@@ -382,7 +376,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
382 ret = 0; 376 ret = 0;
383 } 377 }
384 dqstats.writes++; 378 dqstats.writes++;
385 freedqbuf(ddquot); 379 kfree(ddquot);
386 380
387 return ret; 381 return ret;
388} 382}
@@ -393,7 +387,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
393 uint blk) 387 uint blk)
394{ 388{
395 struct qt_disk_dqdbheader *dh; 389 struct qt_disk_dqdbheader *dh;
396 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 390 char *buf = getdqbuf(info->dqi_usable_bs);
397 int ret = 0; 391 int ret = 0;
398 392
399 if (!buf) 393 if (!buf)
@@ -444,7 +438,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
444 } 438 }
445 dquot->dq_off = 0; /* Quota is now unattached */ 439 dquot->dq_off = 0; /* Quota is now unattached */
446out_buf: 440out_buf:
447 freedqbuf(buf); 441 kfree(buf);
448 return ret; 442 return ret;
449} 443}
450 444
@@ -452,7 +446,7 @@ out_buf:
452static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, 446static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
453 uint *blk, int depth) 447 uint *blk, int depth)
454{ 448{
455 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 449 char *buf = getdqbuf(info->dqi_usable_bs);
456 int ret = 0; 450 int ret = 0;
457 uint newblk; 451 uint newblk;
458 __le32 *ref = (__le32 *)buf; 452 __le32 *ref = (__le32 *)buf;
@@ -475,9 +469,8 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
475 int i; 469 int i;
476 ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0); 470 ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);
477 /* Block got empty? */ 471 /* Block got empty? */
478 for (i = 0; 472 for (i = 0; i < (info->dqi_usable_bs >> 2) && !ref[i]; i++)
479 i < (info->dqi_usable_bs >> 2) && !ref[i]; 473 ;
480 i++);
481 /* Don't put the root block into the free block list */ 474 /* Don't put the root block into the free block list */
482 if (i == (info->dqi_usable_bs >> 2) 475 if (i == (info->dqi_usable_bs >> 2)
483 && *blk != QT_TREEOFF) { 476 && *blk != QT_TREEOFF) {
@@ -491,7 +484,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
491 } 484 }
492 } 485 }
493out_buf: 486out_buf:
494 freedqbuf(buf); 487 kfree(buf);
495 return ret; 488 return ret;
496} 489}
497 490
@@ -510,7 +503,7 @@ EXPORT_SYMBOL(qtree_delete_dquot);
510static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, 503static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
511 struct dquot *dquot, uint blk) 504 struct dquot *dquot, uint blk)
512{ 505{
513 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 506 char *buf = getdqbuf(info->dqi_usable_bs);
514 loff_t ret = 0; 507 loff_t ret = 0;
515 int i; 508 int i;
516 char *ddquot; 509 char *ddquot;
@@ -522,9 +515,10 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
522 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk); 515 printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
523 goto out_buf; 516 goto out_buf;
524 } 517 }
525 for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader); 518 for (i = 0, ddquot = buf + sizeof(struct qt_disk_dqdbheader);
526 i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot); 519 i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
527 i++, ddquot += info->dqi_entry_size); 520 i++, ddquot += info->dqi_entry_size)
521 ;
528 if (i == qtree_dqstr_in_blk(info)) { 522 if (i == qtree_dqstr_in_blk(info)) {
529 printk(KERN_ERR "VFS: Quota for id %u referenced " 523 printk(KERN_ERR "VFS: Quota for id %u referenced "
530 "but not present.\n", dquot->dq_id); 524 "but not present.\n", dquot->dq_id);
@@ -535,7 +529,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
535 qt_disk_dqdbheader) + i * info->dqi_entry_size; 529 qt_disk_dqdbheader) + i * info->dqi_entry_size;
536 } 530 }
537out_buf: 531out_buf:
538 freedqbuf(buf); 532 kfree(buf);
539 return ret; 533 return ret;
540} 534}
541 535
@@ -543,7 +537,7 @@ out_buf:
543static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, 537static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
544 struct dquot *dquot, uint blk, int depth) 538 struct dquot *dquot, uint blk, int depth)
545{ 539{
546 dqbuf_t buf = getdqbuf(info->dqi_usable_bs); 540 char *buf = getdqbuf(info->dqi_usable_bs);
547 loff_t ret = 0; 541 loff_t ret = 0;
548 __le32 *ref = (__le32 *)buf; 542 __le32 *ref = (__le32 *)buf;
549 543
@@ -563,7 +557,7 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
563 else 557 else
564 ret = find_block_dqentry(info, dquot, blk); 558 ret = find_block_dqentry(info, dquot, blk);
565out_buf: 559out_buf:
566 freedqbuf(buf); 560 kfree(buf);
567 return ret; 561 return ret;
568} 562}
569 563
@@ -579,7 +573,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
579 int type = dquot->dq_type; 573 int type = dquot->dq_type;
580 struct super_block *sb = dquot->dq_sb; 574 struct super_block *sb = dquot->dq_sb;
581 loff_t offset; 575 loff_t offset;
582 dqbuf_t ddquot; 576 char *ddquot;
583 int ret = 0; 577 int ret = 0;
584 578
585#ifdef __QUOTA_QT_PARANOIA 579#ifdef __QUOTA_QT_PARANOIA
@@ -607,8 +601,8 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
607 ddquot = getdqbuf(info->dqi_entry_size); 601 ddquot = getdqbuf(info->dqi_entry_size);
608 if (!ddquot) 602 if (!ddquot)
609 return -ENOMEM; 603 return -ENOMEM;
610 ret = sb->s_op->quota_read(sb, type, (char *)ddquot, 604 ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size,
611 info->dqi_entry_size, dquot->dq_off); 605 dquot->dq_off);
612 if (ret != info->dqi_entry_size) { 606 if (ret != info->dqi_entry_size) {
613 if (ret >= 0) 607 if (ret >= 0)
614 ret = -EIO; 608 ret = -EIO;
@@ -616,7 +610,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
616 "structure for id %u.\n", dquot->dq_id); 610 "structure for id %u.\n", dquot->dq_id);
617 set_bit(DQ_FAKE_B, &dquot->dq_flags); 611 set_bit(DQ_FAKE_B, &dquot->dq_flags);
618 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); 612 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
619 freedqbuf(ddquot); 613 kfree(ddquot);
620 goto out; 614 goto out;
621 } 615 }
622 spin_lock(&dq_data_lock); 616 spin_lock(&dq_data_lock);
@@ -627,7 +621,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
627 !dquot->dq_dqb.dqb_isoftlimit) 621 !dquot->dq_dqb.dqb_isoftlimit)
628 set_bit(DQ_FAKE_B, &dquot->dq_flags); 622 set_bit(DQ_FAKE_B, &dquot->dq_flags);
629 spin_unlock(&dq_data_lock); 623 spin_unlock(&dq_data_lock);
630 freedqbuf(ddquot); 624 kfree(ddquot);
631out: 625out:
632 dqstats.reads++; 626 dqstats.reads++;
633 return ret; 627 return ret;