From: Dave Chinner Date: Mon, 4 Aug 2014 02:43:26 +0000 (+1000) Subject: xfs: quotacheck leaves dquot buffers without verifiers X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=5fd364fee81a7888af806e42ed8a91c845894f2d;p=linux-beck.git xfs: quotacheck leaves dquot buffers without verifiers When running xfs/305, I noticed that quotacheck was flushing dquot buffers that did not have the xfs_dquot_buf_ops verifiers attached: XFS (vdb): _xfs_buf_ioapply: no ops on block 0x1dc8/0x1dc8 ffff880052489000: 44 51 01 04 00 00 65 b8 00 00 00 00 00 00 00 00 DQ....e......... ffff880052489010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ffff880052489020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ffff880052489030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ CPU: 1 PID: 2376 Comm: mount Not tainted 3.16.0-rc2-dgc+ #306 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 ffff88006fe38000 ffff88004a0ffae8 ffffffff81cf1cca 0000000000000001 ffff88004a0ffb88 ffffffff814d50ca 000010004a0ffc70 0000000000000000 ffff88006be56dc4 0000000000000021 0000000000001dc8 ffff88007c773d80 Call Trace: [] dump_stack+0x45/0x56 [] _xfs_buf_ioapply+0x3ca/0x3d0 [] ? wake_up_state+0x20/0x20 [] ? xfs_bdstrat_cb+0x55/0xb0 [] xfs_buf_iorequest+0x6b/0xd0 [] xfs_bdstrat_cb+0x55/0xb0 [] __xfs_buf_delwri_submit+0x15b/0x220 [] ? xfs_buf_delwri_submit+0x30/0x90 [] xfs_buf_delwri_submit+0x30/0x90 [] xfs_qm_quotacheck+0x17d/0x3c0 [] xfs_qm_mount_quotas+0x151/0x1e0 [] xfs_mountfs+0x56c/0x7d0 [] xfs_fs_fill_super+0x2c2/0x340 [] mount_bdev+0x194/0x1d0 [] ? xfs_finish_flags+0x170/0x170 [] xfs_fs_mount+0x15/0x20 [] mount_fs+0x39/0x1b0 [] vfs_kern_mount+0x67/0x120 [] do_mount+0x23e/0xad0 [] ? __get_free_pages+0xe/0x50 [] ? copy_mount_options+0x36/0x150 [] SyS_mount+0x83/0xc0 [] tracesys+0xdd/0xe2 This was caused by dquot buffer readahead not attaching a verifier structure to the buffer when readahead was issued, resulting in the followup read of the buffer finding a valid buffer and so not attaching new verifiers to the buffer as part of the read. Also, when a verifier failure occurs, we then read the buffer without verifiers. Attach the verifiers manually after this read so that if the buffer is then written it will be verified that the corruption has been repaired. Further, when flushing a dquot we don't ask for a verifier when reading in the dquot buffer the dquot belongs to. Most of the time this isn't an issue because the buffer is still cached, but when it is not cached it will result in writing the dquot buffer without having the verfier attached. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 8a44a79f49af..63c2de49f61d 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -974,7 +974,8 @@ xfs_qm_dqflush( * Get the buffer containing the on-disk dquot */ error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno, - mp->m_quotainfo->qi_dqchunklen, 0, &bp, NULL); + mp->m_quotainfo->qi_dqchunklen, 0, &bp, + &xfs_dquot_buf_ops); if (error) goto out_unlock; diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index ba284f6469db..e261547717b7 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -1005,6 +1005,12 @@ xfs_qm_dqiter_bufs( if (error) break; + /* + * A corrupt buffer might not have a verifier attached, so + * make sure we have the correct one attached before writeback + * occurs. + */ + bp->b_ops = &xfs_dquot_buf_ops; xfs_qm_reset_dqcounts(mp, bp, firstid, type); xfs_buf_delwri_queue(bp, buffer_list); xfs_buf_relse(bp); @@ -1090,7 +1096,7 @@ xfs_qm_dqiterate( xfs_buf_readahead(mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, rablkno), mp->m_quotainfo->qi_dqchunklen, - NULL); + &xfs_dquot_buf_ops); rablkno++; } }