On Tue, Aug 28, 2018 at 1:27 AM, Jan Kara <jack@xxxxxxx> wrote: > Hi! > > On Mon 27-08-18 12:01:10, Liu Bo wrote: >> I've run into a problem that "repquota" doesn't always show the latest >> quota stats when using journaled quota of v2, "aquota.group". >> >> Here's the steps: >> 1. quotacheck -cug /mnt >> 2. quotaon -g /mnt >> 3. setquota -g 0 0 2G 0 0 /mnt >> 4. repquota -g /mnt >> >> # in step 4, it didn't always show 2G as the hardlimit >> >> I straced repquota and had realized that it does call both ->sync_fs() >> and sync_blockdev() and then truncates quota file's page cache to >> avoid userspace programs reading stale quota stats. However, the >> changes that "setquota" writes to quota files are stored as metadata >> in ext4 and the "bh" is then marked as "jbddirty". At the ->sync_fs() >> time, if the bh is modified by a later transaction while committing >> ext4's journal, the journal bh "jh" makes it to disk while the "bh" is >> not, and the "bh" is again queued in BJ_Metadata list and marked >> "jbddirty", the point is "bh" is not marked as dirty so that >> sync_blockdev() is not able to flush it to disk, then the end result >> is that quota file "aquota.group" still has stale data which >> "repquota" is reading and showing. >> >> I found the above in an old 3.x kernel, but I've checked that the >> logic also applied to 4.18. >> >> I was wondering if it was a known problem or am I missing anything? > > I was not aware of this problem but you are right that if the buffer with > latest quota data gets modified after repquota(8) calls ->sync_fs() and > before it calls sync_blockdev(), then sync_blockdev() won't checkpoint the > data (write them to final location on disk) and thus repquota(8) won't see > them when reading quota information. This is inherent to how JBD2 > journalling works and is difficult to avoid (the only way I currently see > is to freeze the journal which also forces checkpointing of all the > transactions but that is much more heavyweight operation). > > The problem with data visibility in aquota.* files also exists in 4.18 > kernel, however newer kernels (and quota tools) have different way of > reporting quotas - they have Q_GETNEXTQUOTA quotactl which repquota(8) will > use if available and that fixes this problem as repquota(8) no longer needs > to read quota files directly. > I see, so Q_GETNEXTQUOTA will call do_get_dqblk() to get the in-memory latest quota. Will check the latest tool, thanks for the reply. thanks, liubo