Commit 1907131bbeabb33db313bad34f3ec1a5faedbd64

Authored by Jiaying Zhang
Committed by Jan Kara
1 parent c06bcbfa1e

dquot: Detect partial write error to quota file in write_blk() and add printk_ra…

…telimit for quota error messages

This patch changes quota_tree.c:write_blk() to detect error caused by partial
write to quota file and add a macro to limit control printed quota error
messages so we won't fill up dmesg with a corrupted quota file.

Signed-off-by: Jiaying Zhang <jiayingz@google.com>
Signed-off-by: Jan Kara <jack@suse.cz>

Showing 3 changed files with 36 additions and 22 deletions Side-by-side Diff

fs/quota/quota_tree.c
... ... @@ -60,9 +60,17 @@
60 60 static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
61 61 {
62 62 struct super_block *sb = info->dqi_sb;
  63 + ssize_t ret;
63 64  
64   - return sb->s_op->quota_write(sb, info->dqi_type, buf,
  65 + ret = sb->s_op->quota_write(sb, info->dqi_type, buf,
65 66 info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
  67 + if (ret != info->dqi_usable_bs) {
  68 + q_warn(KERN_WARNING "VFS: dquota write failed on "
  69 + "dev %s\n", sb->s_id);
  70 + if (ret >= 0)
  71 + ret = -EIO;
  72 + }
  73 + return ret;
66 74 }
67 75  
68 76 /* Remove empty block from list and return it */
... ... @@ -152,7 +160,7 @@
152 160 dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
153 161 /* No matter whether write succeeds block is out of list */
154 162 if (write_blk(info, blk, buf) < 0)
155   - printk(KERN_ERR
  163 + q_warn(KERN_ERR
156 164 "VFS: Can't write block (%u) with free entries.\n",
157 165 blk);
158 166 return 0;
... ... @@ -244,7 +252,7 @@
244 252 if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) {
245 253 *err = remove_free_dqentry(info, buf, blk);
246 254 if (*err < 0) {
247   - printk(KERN_ERR "VFS: find_free_dqentry(): Can't "
  255 + q_warn(KERN_ERR "VFS: find_free_dqentry(): Can't "
248 256 "remove block (%u) from entry free list.\n",
249 257 blk);
250 258 goto out_buf;
... ... @@ -268,7 +276,7 @@
268 276 #endif
269 277 *err = write_blk(info, blk, buf);
270 278 if (*err < 0) {
271   - printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota "
  279 + q_warn(KERN_ERR "VFS: find_free_dqentry(): Can't write quota "
272 280 "data block %u.\n", blk);
273 281 goto out_buf;
274 282 }
... ... @@ -303,7 +311,7 @@
303 311 } else {
304 312 ret = read_blk(info, *treeblk, buf);
305 313 if (ret < 0) {
306   - printk(KERN_ERR "VFS: Can't read tree quota block "
  314 + q_warn(KERN_ERR "VFS: Can't read tree quota block "
307 315 "%u.\n", *treeblk);
308 316 goto out_buf;
309 317 }
... ... @@ -365,7 +373,7 @@
365 373 if (!dquot->dq_off) {
366 374 ret = dq_insert_tree(info, dquot);
367 375 if (ret < 0) {
368   - printk(KERN_ERR "VFS: Error %zd occurred while "
  376 + q_warn(KERN_ERR "VFS: Error %zd occurred while "
369 377 "creating quota.\n", ret);
370 378 kfree(ddquot);
371 379 return ret;
... ... @@ -377,7 +385,7 @@
377 385 ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size,
378 386 dquot->dq_off);
379 387 if (ret != info->dqi_entry_size) {
380   - printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
  388 + q_warn(KERN_WARNING "VFS: dquota write failed on dev %s\n",
381 389 sb->s_id);
382 390 if (ret >= 0)
383 391 ret = -ENOSPC;
384 392  
... ... @@ -402,14 +410,14 @@
402 410 if (!buf)
403 411 return -ENOMEM;
404 412 if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {
405   - printk(KERN_ERR "VFS: Quota structure has offset to other "
  413 + q_warn(KERN_ERR "VFS: Quota structure has offset to other "
406 414 "block (%u) than it should (%u).\n", blk,
407 415 (uint)(dquot->dq_off >> info->dqi_blocksize_bits));
408 416 goto out_buf;
409 417 }
410 418 ret = read_blk(info, blk, buf);
411 419 if (ret < 0) {
412   - printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
  420 + q_warn(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
413 421 goto out_buf;
414 422 }
415 423 dh = (struct qt_disk_dqdbheader *)buf;
... ... @@ -419,7 +427,7 @@
419 427 if (ret >= 0)
420 428 ret = put_free_dqblk(info, buf, blk);
421 429 if (ret < 0) {
422   - printk(KERN_ERR "VFS: Can't move quota data block (%u) "
  430 + q_warn(KERN_ERR "VFS: Can't move quota data block (%u) "
423 431 "to free list.\n", blk);
424 432 goto out_buf;
425 433 }
426 434  
... ... @@ -432,14 +440,14 @@
432 440 /* Insert will write block itself */
433 441 ret = insert_free_dqentry(info, buf, blk);
434 442 if (ret < 0) {
435   - printk(KERN_ERR "VFS: Can't insert quota data "
  443 + q_warn(KERN_ERR "VFS: Can't insert quota data "
436 444 "block (%u) to free entry list.\n", blk);
437 445 goto out_buf;
438 446 }
439 447 } else {
440 448 ret = write_blk(info, blk, buf);
441 449 if (ret < 0) {
442   - printk(KERN_ERR "VFS: Can't write quota data "
  450 + q_warn(KERN_ERR "VFS: Can't write quota data "
443 451 "block %u\n", blk);
444 452 goto out_buf;
445 453 }
... ... @@ -464,7 +472,7 @@
464 472 return -ENOMEM;
465 473 ret = read_blk(info, *blk, buf);
466 474 if (ret < 0) {
467   - printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
  475 + q_warn(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
468 476 goto out_buf;
469 477 }
470 478 newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
... ... @@ -488,7 +496,7 @@
488 496 } else {
489 497 ret = write_blk(info, *blk, buf);
490 498 if (ret < 0)
491   - printk(KERN_ERR "VFS: Can't write quota tree "
  499 + q_warn(KERN_ERR "VFS: Can't write quota tree "
492 500 "block %u.\n", *blk);
493 501 }
494 502 }
... ... @@ -521,7 +529,7 @@
521 529 return -ENOMEM;
522 530 ret = read_blk(info, blk, buf);
523 531 if (ret < 0) {
524   - printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
  532 + q_warn(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
525 533 goto out_buf;
526 534 }
527 535 ddquot = buf + sizeof(struct qt_disk_dqdbheader);
... ... @@ -531,7 +539,7 @@
531 539 ddquot += info->dqi_entry_size;
532 540 }
533 541 if (i == qtree_dqstr_in_blk(info)) {
534   - printk(KERN_ERR "VFS: Quota for id %u referenced "
  542 + q_warn(KERN_ERR "VFS: Quota for id %u referenced "
535 543 "but not present.\n", dquot->dq_id);
536 544 ret = -EIO;
537 545 goto out_buf;
... ... @@ -556,7 +564,7 @@
556 564 return -ENOMEM;
557 565 ret = read_blk(info, blk, buf);
558 566 if (ret < 0) {
559   - printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
  567 + q_warn(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
560 568 goto out_buf;
561 569 }
562 570 ret = 0;
... ... @@ -599,7 +607,7 @@
599 607 offset = find_dqentry(info, dquot);
600 608 if (offset <= 0) { /* Entry not present? */
601 609 if (offset < 0)
602   - printk(KERN_ERR "VFS: Can't read quota "
  610 + q_warn(KERN_ERR "VFS: Can't read quota "
603 611 "structure for id %u.\n", dquot->dq_id);
604 612 dquot->dq_off = 0;
605 613 set_bit(DQ_FAKE_B, &dquot->dq_flags);
... ... @@ -617,7 +625,7 @@
617 625 if (ret != info->dqi_entry_size) {
618 626 if (ret >= 0)
619 627 ret = -EIO;
620   - printk(KERN_ERR "VFS: Error while reading quota "
  628 + q_warn(KERN_ERR "VFS: Error while reading quota "
621 629 "structure for id %u.\n", dquot->dq_id);
622 630 set_bit(DQ_FAKE_B, &dquot->dq_flags);
623 631 memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
fs/quota/quota_tree.h
... ... @@ -22,5 +22,11 @@
22 22  
23 23 #define QT_TREEOFF 1 /* Offset of tree in file in blocks */
24 24  
  25 +#define q_warn(fmt, args...) \
  26 +do { \
  27 + if (printk_ratelimit()) \
  28 + printk(fmt, ## args); \
  29 +} while(0)
  30 +
25 31 #endif /* _LINUX_QUOTAIO_TREE_H */
... ... @@ -63,7 +63,7 @@
63 63 size = sb->s_op->quota_read(sb, type, (char *)dqhead,
64 64 sizeof(struct v2_disk_dqheader), 0);
65 65 if (size != sizeof(struct v2_disk_dqheader)) {
66   - printk(KERN_WARNING "quota_v2: Failed header read:"
  66 + q_warn(KERN_WARNING "quota_v2: Failed header read:"
67 67 " expected=%zd got=%zd\n",
68 68 sizeof(struct v2_disk_dqheader), size);
69 69 return 0;
... ... @@ -106,7 +106,7 @@
106 106 size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
107 107 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
108 108 if (size != sizeof(struct v2_disk_dqinfo)) {
109   - printk(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n",
  109 + q_warn(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n",
110 110 sb->s_id);
111 111 return -1;
112 112 }
... ... @@ -167,7 +167,7 @@
167 167 size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
168 168 sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
169 169 if (size != sizeof(struct v2_disk_dqinfo)) {
170   - printk(KERN_WARNING "Can't write info structure on device %s.\n",
  170 + q_warn(KERN_WARNING "Can't write info structure on device %s.\n",
171 171 sb->s_id);
172 172 return -1;
173 173 }